Remove usage of VoEAudioProcessing from WVoE/MC.
Calling APM and TransmitMixer directly instead. BUG=webrtc:4690 TBR=peah@webrtc.org Review-Url: https://codereview.webrtc.org/2681033010 Cr-Commit-Position: refs/heads/master@{#16734}
This commit is contained in:
parent
11c9eafc69
commit
76377c55b7
@ -101,6 +101,8 @@ rtc_static_library("rtc_media") {
|
||||
libs = []
|
||||
deps = []
|
||||
sources = [
|
||||
"engine/apm_helpers.cc",
|
||||
"engine/apm_helpers.h",
|
||||
"engine/internaldecoderfactory.cc",
|
||||
"engine/internaldecoderfactory.h",
|
||||
"engine/internalencoderfactory.cc",
|
||||
@ -319,6 +321,7 @@ if (rtc_include_tests) {
|
||||
"base/videocapturer_unittest.cc",
|
||||
"base/videocommon_unittest.cc",
|
||||
"base/videoengine_unittest.h",
|
||||
"engine/apm_helpers_unittest.cc",
|
||||
"engine/internaldecoderfactory_unittest.cc",
|
||||
"engine/nullwebrtcvideoengine_unittest.cc",
|
||||
"engine/payload_type_mapper_unittest.cc",
|
||||
|
||||
173
webrtc/media/engine/apm_helpers.cc
Normal file
173
webrtc/media/engine/apm_helpers.cc
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/media/engine/apm_helpers.h"
|
||||
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/modules/audio_device/include/audio_device.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/voice_engine/transmit_mixer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace apm_helpers {
|
||||
|
||||
AgcConfig GetAgcConfig(AudioProcessing* apm) {
|
||||
RTC_DCHECK(apm);
|
||||
AgcConfig result;
|
||||
result.targetLeveldBOv = apm->gain_control()->target_level_dbfs();
|
||||
result.digitalCompressionGaindB = apm->gain_control()->compression_gain_db();
|
||||
result.limiterEnable = apm->gain_control()->is_limiter_enabled();
|
||||
return result;
|
||||
}
|
||||
|
||||
void SetAgcConfig(AudioProcessing* apm,
|
||||
const AgcConfig& config) {
|
||||
RTC_DCHECK(apm);
|
||||
GainControl* gc = apm->gain_control();
|
||||
if (gc->set_target_level_dbfs(config.targetLeveldBOv) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to set target level: " << config.targetLeveldBOv;
|
||||
}
|
||||
if (gc->set_compression_gain_db(config.digitalCompressionGaindB) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to set compression gain: "
|
||||
<< config.digitalCompressionGaindB;
|
||||
}
|
||||
if (gc->enable_limiter(config.limiterEnable) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to set limiter on/off: " << config.limiterEnable;
|
||||
}
|
||||
}
|
||||
|
||||
void SetAgcStatus(AudioProcessing* apm,
|
||||
AudioDeviceModule* adm,
|
||||
bool enable,
|
||||
AgcModes mode) {
|
||||
RTC_DCHECK(apm);
|
||||
RTC_DCHECK(adm);
|
||||
#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
|
||||
RTC_DCHECK_EQ(kAgcFixedDigital, mode);
|
||||
GainControl::Mode agc_mode = GainControl::kFixedDigital;
|
||||
#else
|
||||
RTC_DCHECK_EQ(kAgcAdaptiveAnalog, mode);
|
||||
GainControl::Mode agc_mode = GainControl::kAdaptiveAnalog;
|
||||
#endif
|
||||
GainControl* gc = apm->gain_control();
|
||||
if (gc->set_mode(agc_mode) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to set AGC mode: " << agc_mode;
|
||||
return;
|
||||
}
|
||||
if (gc->Enable(enable) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable AGC: " << enable;
|
||||
return;
|
||||
}
|
||||
// Set AGC state in the ADM when adaptive AGC mode has been selected.
|
||||
if (adm->SetAGC(enable && agc_mode == GainControl::kAdaptiveAnalog) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to set AGC mode in ADM: " << enable;
|
||||
return;
|
||||
}
|
||||
LOG(LS_INFO) << "AGC set to " << enable << " with mode " << mode;
|
||||
}
|
||||
|
||||
void SetEcStatus(AudioProcessing* apm,
|
||||
bool enable,
|
||||
EcModes mode) {
|
||||
RTC_DCHECK(apm);
|
||||
RTC_DCHECK(mode == kEcConference || mode == kEcAecm) << "mode: " << mode;
|
||||
EchoCancellation* ec = apm->echo_cancellation();
|
||||
EchoControlMobile* ecm = apm->echo_control_mobile();
|
||||
if (mode == kEcConference) {
|
||||
// Disable the AECM before enabling the AEC.
|
||||
if (enable && ecm->is_enabled() && ecm->Enable(false) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to disable AECM.";
|
||||
return;
|
||||
}
|
||||
if (ec->Enable(enable) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable AEC: " << enable;
|
||||
return;
|
||||
}
|
||||
if (ec->set_suppression_level(EchoCancellation::kHighSuppression)
|
||||
!= 0) {
|
||||
LOG(LS_ERROR) << "Failed to set high AEC aggressiveness.";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Disable the AEC before enabling the AECM.
|
||||
if (enable && ec->is_enabled() && ec->Enable(false) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to disable AEC.";
|
||||
return;
|
||||
}
|
||||
if (ecm->Enable(enable) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable AECM: " << enable;
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG(LS_INFO) << "Echo control set to " << enable << " with mode " << mode;
|
||||
}
|
||||
|
||||
void SetEcMetricsStatus(AudioProcessing* apm, bool enable) {
|
||||
RTC_DCHECK(apm);
|
||||
if ((apm->echo_cancellation()->enable_metrics(enable) != 0) ||
|
||||
(apm->echo_cancellation()->enable_delay_logging(enable) != 0)) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable EC metrics: " << enable;
|
||||
return;
|
||||
}
|
||||
LOG(LS_INFO) << "EC metrics set to " << enable;
|
||||
}
|
||||
|
||||
void SetAecmMode(AudioProcessing* apm, bool enable) {
|
||||
RTC_DCHECK(apm);
|
||||
EchoControlMobile* ecm = apm->echo_control_mobile();
|
||||
RTC_DCHECK_EQ(EchoControlMobile::kSpeakerphone, ecm->routing_mode());
|
||||
if (ecm->enable_comfort_noise(enable) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable CNG: " << enable;
|
||||
return;
|
||||
}
|
||||
LOG(LS_INFO) << "CNG set to " << enable;
|
||||
}
|
||||
|
||||
void SetNsStatus(AudioProcessing* apm, bool enable) {
|
||||
RTC_DCHECK(apm);
|
||||
NoiseSuppression* ns = apm->noise_suppression();
|
||||
if (ns->set_level(NoiseSuppression::kHigh) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to set high NS level.";
|
||||
return;
|
||||
}
|
||||
if (ns->Enable(enable) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable NS: " << enable;
|
||||
return;
|
||||
}
|
||||
LOG(LS_INFO) << "NS set to " << enable;
|
||||
}
|
||||
|
||||
void SetTypingDetectionStatus(AudioProcessing* apm, bool enable) {
|
||||
RTC_DCHECK(apm);
|
||||
#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||
// Typing detection takes place in TransmitMixer::PrepareDemux() and
|
||||
// TransmitMixer::TypingDetection(). The typing detection algorithm takes as
|
||||
// input two booleans:
|
||||
// 1. A signal whether a key was pressed during the audio frame.
|
||||
// 2. Whether VAD is active or not.
|
||||
// TransmitMixer will not even call the detector if APM has set kVadUnknown in
|
||||
// the audio frame after near end processing, so enabling/disabling VAD is
|
||||
// sufficient for turning typing detection on/off.
|
||||
// TODO(solenberg): Rather than relying on a side effect, consider forcing the
|
||||
// feature on/off in TransmitMixer.
|
||||
VoiceDetection* vd = apm->voice_detection();
|
||||
if (vd->Enable(enable)) {
|
||||
LOG(LS_ERROR) << "Failed to enable/disable VAD: " << enable;
|
||||
return;
|
||||
}
|
||||
if (vd->set_likelihood(VoiceDetection::kVeryLowLikelihood)) {
|
||||
LOG(LS_ERROR) << "Failed to set low VAD likelihood.";
|
||||
return;
|
||||
}
|
||||
LOG(LS_INFO) << "VAD set to " << enable << " for typing detection.";
|
||||
#endif
|
||||
}
|
||||
} // namespace apm_helpers
|
||||
} // namespace webrtc
|
||||
41
webrtc/media/engine/apm_helpers.h
Normal file
41
webrtc/media/engine/apm_helpers.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MEDIA_ENGINE_APM_HELPERS_H_
|
||||
#define WEBRTC_MEDIA_ENGINE_APM_HELPERS_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioProcessing;
|
||||
class AudioDeviceModule;
|
||||
|
||||
namespace apm_helpers {
|
||||
|
||||
AgcConfig GetAgcConfig(AudioProcessing* apm);
|
||||
void SetAgcConfig(AudioProcessing* apm,
|
||||
const AgcConfig& config);
|
||||
void SetAgcStatus(AudioProcessing* apm,
|
||||
AudioDeviceModule* adm,
|
||||
bool enable,
|
||||
AgcModes mode);
|
||||
void SetEcStatus(AudioProcessing* apm,
|
||||
bool enable,
|
||||
EcModes mode);
|
||||
void SetEcMetricsStatus(AudioProcessing* apm, bool enable);
|
||||
void SetAecmMode(AudioProcessing* apm, bool enable_cng);
|
||||
void SetNsStatus(AudioProcessing* apm, bool enable);
|
||||
void SetTypingDetectionStatus(AudioProcessing* apm, bool enable);
|
||||
|
||||
} // namespace apm_helpers
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MEDIA_ENGINE_APM_HELPERS_H_
|
||||
283
webrtc/media/engine/apm_helpers_unittest.cc
Normal file
283
webrtc/media/engine/apm_helpers_unittest.cc
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/media/engine/apm_helpers.h"
|
||||
|
||||
#include "webrtc/media/engine/webrtcvoe.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h"
|
||||
#include "webrtc/modules/audio_device/include/mock_audio_device.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/voice_engine/transmit_mixer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
constexpr AgcConfig kDefaultAgcConfig = { 3, 9, true };
|
||||
|
||||
struct TestHelper {
|
||||
TestHelper() {
|
||||
// This replicates the conditions from voe_auto_test.
|
||||
Config config;
|
||||
config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
|
||||
EXPECT_EQ(0, voe_wrapper_.base()->Init(
|
||||
&mock_audio_device_,
|
||||
AudioProcessing::Create(config),
|
||||
MockAudioDecoderFactory::CreateEmptyFactory()));
|
||||
}
|
||||
|
||||
AudioProcessing* apm() {
|
||||
return voe_wrapper_.base()->audio_processing();
|
||||
}
|
||||
|
||||
const AudioProcessing* apm() const {
|
||||
return voe_wrapper_.base()->audio_processing();
|
||||
}
|
||||
|
||||
test::MockAudioDeviceModule* adm() {
|
||||
return &mock_audio_device_;
|
||||
}
|
||||
|
||||
voe::TransmitMixer* transmit_mixer() {
|
||||
return voe_wrapper_.base()->transmit_mixer();
|
||||
}
|
||||
|
||||
bool GetEcMetricsStatus() const {
|
||||
EchoCancellation* ec = apm()->echo_cancellation();
|
||||
bool metrics_enabled = ec->are_metrics_enabled();
|
||||
EXPECT_EQ(metrics_enabled, ec->is_delay_logging_enabled());
|
||||
return metrics_enabled;
|
||||
}
|
||||
|
||||
bool CanGetEcMetrics() const {
|
||||
EchoCancellation* ec = apm()->echo_cancellation();
|
||||
EchoCancellation::Metrics metrics;
|
||||
int metrics_result = ec->GetMetrics(&metrics);
|
||||
int median = 0;
|
||||
int std = 0;
|
||||
float fraction = 0;
|
||||
int delay_metrics_result = ec->GetDelayMetrics(&median, &std, &fraction);
|
||||
return metrics_result == AudioProcessing::kNoError &&
|
||||
delay_metrics_result == AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
private:
|
||||
testing::NiceMock<test::MockAudioDeviceModule> mock_audio_device_;
|
||||
cricket::VoEWrapper voe_wrapper_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(ApmHelpersTest, AgcConfig_DefaultConfiguration) {
|
||||
TestHelper helper;
|
||||
AgcConfig agc_config =
|
||||
apm_helpers::GetAgcConfig(helper.apm());
|
||||
|
||||
EXPECT_EQ(kDefaultAgcConfig.targetLeveldBOv, agc_config.targetLeveldBOv);
|
||||
EXPECT_EQ(kDefaultAgcConfig.digitalCompressionGaindB,
|
||||
agc_config.digitalCompressionGaindB);
|
||||
EXPECT_EQ(kDefaultAgcConfig.limiterEnable, agc_config.limiterEnable);
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, AgcConfig_GetAndSet) {
|
||||
const AgcConfig agc_config = { 11, 17, false };
|
||||
|
||||
TestHelper helper;
|
||||
apm_helpers::SetAgcConfig(helper.apm(), agc_config);
|
||||
AgcConfig actual_config =
|
||||
apm_helpers::GetAgcConfig(helper.apm());
|
||||
|
||||
EXPECT_EQ(agc_config.digitalCompressionGaindB,
|
||||
actual_config.digitalCompressionGaindB);
|
||||
EXPECT_EQ(agc_config.limiterEnable,
|
||||
actual_config.limiterEnable);
|
||||
EXPECT_EQ(agc_config.targetLeveldBOv,
|
||||
actual_config.targetLeveldBOv);
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, AgcStatus_DefaultMode) {
|
||||
TestHelper helper;
|
||||
GainControl* gc = helper.apm()->gain_control();
|
||||
#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
|
||||
EXPECT_FALSE(gc->is_enabled());
|
||||
EXPECT_EQ(GainControl::kFixedDigital, gc->mode());
|
||||
#else
|
||||
EXPECT_TRUE(gc->is_enabled());
|
||||
EXPECT_EQ(GainControl::kAdaptiveAnalog, gc->mode());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, AgcStatus_EnableDisable) {
|
||||
TestHelper helper;
|
||||
GainControl* gc = helper.apm()->gain_control();
|
||||
#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
|
||||
apm_helpers::SetAgcStatus(helper.apm(), helper.adm(), false,
|
||||
kAgcFixedDigital);
|
||||
EXPECT_FALSE(gc->is_enabled());
|
||||
EXPECT_EQ(GainControl::kFixedDigital, gc->mode());
|
||||
|
||||
apm_helpers::SetAgcStatus(helper.apm(), helper.adm(), true,
|
||||
kAgcFixedDigital);
|
||||
EXPECT_TRUE(gc->is_enabled());
|
||||
EXPECT_EQ(GainControl::kFixedDigital, gc->mode());
|
||||
#else
|
||||
EXPECT_CALL(*helper.adm(), SetAGC(false)).WillOnce(testing::Return(0));
|
||||
apm_helpers::SetAgcStatus(helper.apm(), helper.adm(), false,
|
||||
kAgcAdaptiveAnalog);
|
||||
EXPECT_FALSE(gc->is_enabled());
|
||||
EXPECT_EQ(GainControl::kAdaptiveAnalog, gc->mode());
|
||||
|
||||
EXPECT_CALL(*helper.adm(), SetAGC(true)).WillOnce(testing::Return(0));
|
||||
apm_helpers::SetAgcStatus(helper.apm(), helper.adm(), true,
|
||||
kAgcAdaptiveAnalog);
|
||||
EXPECT_TRUE(gc->is_enabled());
|
||||
EXPECT_EQ(GainControl::kAdaptiveAnalog, gc->mode());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, EcStatus_DefaultMode) {
|
||||
TestHelper helper;
|
||||
EchoCancellation* ec = helper.apm()->echo_cancellation();
|
||||
EchoControlMobile* ecm = helper.apm()->echo_control_mobile();
|
||||
EXPECT_FALSE(ec->is_enabled());
|
||||
EXPECT_FALSE(ecm->is_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, EcStatus_EnableDisable) {
|
||||
TestHelper helper;
|
||||
EchoCancellation* ec = helper.apm()->echo_cancellation();
|
||||
EchoControlMobile* ecm = helper.apm()->echo_control_mobile();
|
||||
|
||||
apm_helpers::SetEcStatus(helper.apm(), true, kEcAecm);
|
||||
EXPECT_FALSE(ec->is_enabled());
|
||||
EXPECT_TRUE(ecm->is_enabled());
|
||||
|
||||
apm_helpers::SetEcStatus(helper.apm(), false, kEcAecm);
|
||||
EXPECT_FALSE(ec->is_enabled());
|
||||
EXPECT_FALSE(ecm->is_enabled());
|
||||
|
||||
apm_helpers::SetEcStatus(helper.apm(), true, kEcConference);
|
||||
EXPECT_TRUE(ec->is_enabled());
|
||||
EXPECT_FALSE(ecm->is_enabled());
|
||||
EXPECT_EQ(EchoCancellation::kHighSuppression, ec->suppression_level());
|
||||
|
||||
apm_helpers::SetEcStatus(helper.apm(), false, kEcConference);
|
||||
EXPECT_FALSE(ec->is_enabled());
|
||||
EXPECT_FALSE(ecm->is_enabled());
|
||||
EXPECT_EQ(EchoCancellation::kHighSuppression, ec->suppression_level());
|
||||
|
||||
apm_helpers::SetEcStatus(helper.apm(), true, kEcAecm);
|
||||
EXPECT_FALSE(ec->is_enabled());
|
||||
EXPECT_TRUE(ecm->is_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, EcMetrics_DefaultMode) {
|
||||
TestHelper helper;
|
||||
apm_helpers::SetEcStatus(helper.apm(), true, kEcConference);
|
||||
EXPECT_TRUE(helper.GetEcMetricsStatus());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, EcMetrics_CanEnableDisable) {
|
||||
TestHelper helper;
|
||||
apm_helpers::SetEcStatus(helper.apm(), true, kEcConference);
|
||||
|
||||
apm_helpers::SetEcMetricsStatus(helper.apm(), true);
|
||||
EXPECT_TRUE(helper.GetEcMetricsStatus());
|
||||
apm_helpers::SetEcMetricsStatus(helper.apm(), false);
|
||||
EXPECT_FALSE(helper.GetEcMetricsStatus());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, EcMetrics_NoStatsUnlessEcMetricsAndEcEnabled) {
|
||||
TestHelper helper;
|
||||
EXPECT_FALSE(helper.CanGetEcMetrics());
|
||||
|
||||
apm_helpers::SetEcMetricsStatus(helper.apm(), true);
|
||||
EXPECT_FALSE(helper.CanGetEcMetrics());
|
||||
|
||||
apm_helpers::SetEcStatus(helper.apm(), true, kEcConference);
|
||||
EXPECT_TRUE(helper.CanGetEcMetrics());
|
||||
|
||||
apm_helpers::SetEcMetricsStatus(helper.apm(), false);
|
||||
EXPECT_FALSE(helper.CanGetEcMetrics());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, AecmMode_DefaultMode) {
|
||||
TestHelper helper;
|
||||
EchoControlMobile* ecm = helper.apm()->echo_control_mobile();
|
||||
EXPECT_EQ(EchoControlMobile::kSpeakerphone, ecm->routing_mode());
|
||||
EXPECT_TRUE(ecm->is_comfort_noise_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, AecmMode_EnableDisableCng) {
|
||||
TestHelper helper;
|
||||
EchoControlMobile* ecm = helper.apm()->echo_control_mobile();
|
||||
apm_helpers::SetAecmMode(helper.apm(), false);
|
||||
EXPECT_FALSE(ecm->is_comfort_noise_enabled());
|
||||
apm_helpers::SetAecmMode(helper.apm(), true);
|
||||
EXPECT_TRUE(ecm->is_comfort_noise_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, NsStatus_DefaultMode) {
|
||||
TestHelper helper;
|
||||
NoiseSuppression* ns = helper.apm()->noise_suppression();
|
||||
EXPECT_EQ(NoiseSuppression::kModerate, ns->level());
|
||||
EXPECT_FALSE(ns->is_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, NsStatus_EnableDisable) {
|
||||
TestHelper helper;
|
||||
NoiseSuppression* ns = helper.apm()->noise_suppression();
|
||||
apm_helpers::SetNsStatus(helper.apm(), true);
|
||||
EXPECT_EQ(NoiseSuppression::kHigh, ns->level());
|
||||
EXPECT_TRUE(ns->is_enabled());
|
||||
apm_helpers::SetNsStatus(helper.apm(), false);
|
||||
EXPECT_EQ(NoiseSuppression::kHigh, ns->level());
|
||||
EXPECT_FALSE(ns->is_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, TypingDetectionStatus_DefaultMode) {
|
||||
TestHelper helper;
|
||||
VoiceDetection* vd = helper.apm()->voice_detection();
|
||||
EXPECT_FALSE(vd->is_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, TypingDetectionStatus_EnableDisable) {
|
||||
TestHelper helper;
|
||||
VoiceDetection* vd = helper.apm()->voice_detection();
|
||||
apm_helpers::SetTypingDetectionStatus(helper.apm(), true);
|
||||
EXPECT_TRUE(vd->is_enabled());
|
||||
apm_helpers::SetTypingDetectionStatus(helper.apm(), false);
|
||||
EXPECT_FALSE(vd->is_enabled());
|
||||
}
|
||||
|
||||
// TODO(solenberg): Move this test to a better place - added here for the sake
|
||||
// of duplicating all relevant tests from audio_processing_test.cc.
|
||||
TEST(ApmHelpersTest, HighPassFilter_DefaultMode) {
|
||||
TestHelper helper;
|
||||
EXPECT_TRUE(helper.apm()->high_pass_filter()->is_enabled());
|
||||
}
|
||||
|
||||
// TODO(solenberg): Move this test to a better place - added here for the sake
|
||||
// of duplicating all relevant tests from audio_processing_test.cc.
|
||||
TEST(ApmHelpersTest, StereoSwapping_DefaultMode) {
|
||||
TestHelper helper;
|
||||
EXPECT_FALSE(helper.transmit_mixer()->IsStereoChannelSwappingEnabled());
|
||||
}
|
||||
|
||||
// TODO(solenberg): Move this test to a better place - added here for the sake
|
||||
// of duplicating all relevant tests from audio_processing_test.cc.
|
||||
TEST(ApmHelpersTest, StereoSwapping_EnableDisable) {
|
||||
TestHelper helper;
|
||||
helper.transmit_mixer()->EnableStereoChannelSwapping(true);
|
||||
EXPECT_TRUE(helper.transmit_mixer()->IsStereoChannelSwappingEnabled());
|
||||
helper.transmit_mixer()->EnableStereoChannelSwapping(false);
|
||||
EXPECT_FALSE(helper.transmit_mixer()->IsStereoChannelSwappingEnabled());
|
||||
}
|
||||
} // namespace webrtc
|
||||
@ -27,6 +27,12 @@
|
||||
#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace voe {
|
||||
class TransmitMixer;
|
||||
} // namespace voe
|
||||
} // namespace webrtc
|
||||
|
||||
namespace cricket {
|
||||
|
||||
static const int kOpusBandwidthNb = 4000;
|
||||
@ -53,8 +59,7 @@ static const int kOpusBandwidthFb = 20000;
|
||||
#define WEBRTC_FUNC(method, args) int method args override
|
||||
|
||||
class FakeWebRtcVoiceEngine
|
||||
: public webrtc::VoEAudioProcessing,
|
||||
public webrtc::VoEBase, public webrtc::VoECodec,
|
||||
: public webrtc::VoEBase, public webrtc::VoECodec,
|
||||
public webrtc::VoEHardware,
|
||||
public webrtc::VoEVolumeControl {
|
||||
public:
|
||||
@ -64,15 +69,14 @@ class FakeWebRtcVoiceEngine
|
||||
bool neteq_fast_accelerate = false;
|
||||
};
|
||||
|
||||
explicit FakeWebRtcVoiceEngine(webrtc::AudioProcessing* apm) : apm_(apm) {
|
||||
memset(&agc_config_, 0, sizeof(agc_config_));
|
||||
explicit FakeWebRtcVoiceEngine(webrtc::AudioProcessing* apm,
|
||||
webrtc::voe::TransmitMixer* transmit_mixer)
|
||||
: apm_(apm), transmit_mixer_(transmit_mixer) {
|
||||
}
|
||||
~FakeWebRtcVoiceEngine() override {
|
||||
RTC_CHECK(channels_.empty());
|
||||
}
|
||||
|
||||
bool ec_metrics_enabled() const { return ec_metrics_enabled_; }
|
||||
|
||||
bool IsInited() const { return inited_; }
|
||||
int GetLastChannel() const { return last_channel_; }
|
||||
int GetNumChannels() const { return static_cast<int>(channels_.size()); }
|
||||
@ -104,6 +108,9 @@ class FakeWebRtcVoiceEngine
|
||||
webrtc::AudioDeviceModule* audio_device_module() override {
|
||||
return nullptr;
|
||||
}
|
||||
webrtc::voe::TransmitMixer* transmit_mixer() override {
|
||||
return transmit_mixer_;
|
||||
}
|
||||
WEBRTC_FUNC(CreateChannel, ()) {
|
||||
return CreateChannel(webrtc::VoEBase::ChannelConfig());
|
||||
}
|
||||
@ -233,98 +240,6 @@ class FakeWebRtcVoiceEngine
|
||||
WEBRTC_STUB(SetOutputVolumePan, (int channel, float left, float right));
|
||||
WEBRTC_STUB(GetOutputVolumePan, (int channel, float& left, float& right));
|
||||
|
||||
// webrtc::VoEAudioProcessing
|
||||
WEBRTC_FUNC(SetNsStatus, (bool enable, webrtc::NsModes mode)) {
|
||||
ns_enabled_ = enable;
|
||||
ns_mode_ = mode;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetNsStatus, (bool& enabled, webrtc::NsModes& mode)) {
|
||||
enabled = ns_enabled_;
|
||||
mode = ns_mode_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(SetAgcStatus, (bool enable, webrtc::AgcModes mode)) {
|
||||
agc_enabled_ = enable;
|
||||
agc_mode_ = mode;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetAgcStatus, (bool& enabled, webrtc::AgcModes& mode)) {
|
||||
enabled = agc_enabled_;
|
||||
mode = agc_mode_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(SetAgcConfig, (webrtc::AgcConfig config)) {
|
||||
agc_config_ = config;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetAgcConfig, (webrtc::AgcConfig& config)) {
|
||||
config = agc_config_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(SetEcStatus, (bool enable, webrtc::EcModes mode)) {
|
||||
ec_enabled_ = enable;
|
||||
ec_mode_ = mode;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetEcStatus, (bool& enabled, webrtc::EcModes& mode)) {
|
||||
enabled = ec_enabled_;
|
||||
mode = ec_mode_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(EnableDriftCompensation, (bool enable))
|
||||
WEBRTC_BOOL_STUB(DriftCompensationEnabled, ())
|
||||
WEBRTC_VOID_STUB(SetDelayOffsetMs, (int offset))
|
||||
WEBRTC_STUB(DelayOffsetMs, ());
|
||||
WEBRTC_FUNC(SetAecmMode, (webrtc::AecmModes mode, bool enableCNG)) {
|
||||
aecm_mode_ = mode;
|
||||
cng_enabled_ = enableCNG;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetAecmMode, (webrtc::AecmModes& mode, bool& enabledCNG)) {
|
||||
mode = aecm_mode_;
|
||||
enabledCNG = cng_enabled_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(VoiceActivityIndicator, (int channel));
|
||||
WEBRTC_FUNC(SetEcMetricsStatus, (bool enable)) {
|
||||
ec_metrics_enabled_ = enable;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(GetEcMetricsStatus, (bool& enabled));
|
||||
WEBRTC_STUB(GetEchoMetrics, (int& ERL, int& ERLE, int& RERL, int& A_NLP));
|
||||
WEBRTC_STUB(GetEcDelayMetrics, (int& delay_median, int& delay_std,
|
||||
float& fraction_poor_delays));
|
||||
WEBRTC_STUB(StartDebugRecording, (const char* fileNameUTF8));
|
||||
WEBRTC_STUB(StartDebugRecording, (FILE* handle));
|
||||
WEBRTC_STUB(StopDebugRecording, ());
|
||||
WEBRTC_FUNC(SetTypingDetectionStatus, (bool enable)) {
|
||||
typing_detection_enabled_ = enable;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetTypingDetectionStatus, (bool& enabled)) {
|
||||
enabled = typing_detection_enabled_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(TimeSinceLastTyping, (int& seconds));
|
||||
WEBRTC_STUB(SetTypingDetectionParameters, (int timeWindow,
|
||||
int costPerTyping,
|
||||
int reportingThreshold,
|
||||
int penaltyDecay,
|
||||
int typeEventDelay));
|
||||
int EnableHighPassFilter(bool enable) override {
|
||||
highpass_filter_enabled_ = enable;
|
||||
return 0;
|
||||
}
|
||||
bool IsHighPassFilterEnabled() override {
|
||||
return highpass_filter_enabled_;
|
||||
}
|
||||
bool IsStereoChannelSwappingEnabled() override {
|
||||
return stereo_swapping_enabled_;
|
||||
}
|
||||
void EnableStereoChannelSwapping(bool enable) override {
|
||||
stereo_swapping_enabled_ = enable;
|
||||
}
|
||||
size_t GetNetEqCapacity() const {
|
||||
auto ch = channels_.find(last_channel_);
|
||||
RTC_DCHECK(ch != channels_.end());
|
||||
@ -341,20 +256,8 @@ class FakeWebRtcVoiceEngine
|
||||
int last_channel_ = -1;
|
||||
std::map<int, Channel*> channels_;
|
||||
bool fail_create_channel_ = false;
|
||||
bool ec_enabled_ = false;
|
||||
bool ec_metrics_enabled_ = false;
|
||||
bool cng_enabled_ = false;
|
||||
bool ns_enabled_ = false;
|
||||
bool agc_enabled_ = false;
|
||||
bool highpass_filter_enabled_ = false;
|
||||
bool stereo_swapping_enabled_ = false;
|
||||
bool typing_detection_enabled_ = false;
|
||||
webrtc::EcModes ec_mode_ = webrtc::kEcDefault;
|
||||
webrtc::AecmModes aecm_mode_ = webrtc::kAecmSpeakerphone;
|
||||
webrtc::NsModes ns_mode_ = webrtc::kNsDefault;
|
||||
webrtc::AgcModes agc_mode_ = webrtc::kAgcDefault;
|
||||
webrtc::AgcConfig agc_config_;
|
||||
webrtc::AudioProcessing* apm_ = nullptr;
|
||||
webrtc::voe::TransmitMixer* transmit_mixer_ = nullptr;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FakeWebRtcVoiceEngine);
|
||||
};
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/audio_device/include/audio_device.h"
|
||||
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
#include "webrtc/voice_engine/include/voe_codec.h"
|
||||
#include "webrtc/voice_engine/include/voe_errors.h"
|
||||
@ -78,17 +77,15 @@ class scoped_voe_ptr {
|
||||
class VoEWrapper {
|
||||
public:
|
||||
VoEWrapper()
|
||||
: engine_(webrtc::VoiceEngine::Create()), processing_(engine_),
|
||||
: engine_(webrtc::VoiceEngine::Create()),
|
||||
base_(engine_), codec_(engine_), hw_(engine_),
|
||||
volume_(engine_) {
|
||||
}
|
||||
VoEWrapper(webrtc::VoEAudioProcessing* processing,
|
||||
webrtc::VoEBase* base,
|
||||
VoEWrapper(webrtc::VoEBase* base,
|
||||
webrtc::VoECodec* codec,
|
||||
webrtc::VoEHardware* hw,
|
||||
webrtc::VoEVolumeControl* volume)
|
||||
: engine_(NULL),
|
||||
processing_(processing),
|
||||
base_(base),
|
||||
codec_(codec),
|
||||
hw_(hw),
|
||||
@ -96,7 +93,6 @@ class VoEWrapper {
|
||||
}
|
||||
~VoEWrapper() {}
|
||||
webrtc::VoiceEngine* engine() const { return engine_.get(); }
|
||||
webrtc::VoEAudioProcessing* processing() const { return processing_.get(); }
|
||||
webrtc::VoEBase* base() const { return base_.get(); }
|
||||
webrtc::VoECodec* codec() const { return codec_.get(); }
|
||||
webrtc::VoEHardware* hw() const { return hw_.get(); }
|
||||
@ -105,7 +101,6 @@ class VoEWrapper {
|
||||
|
||||
private:
|
||||
scoped_voe_engine engine_;
|
||||
scoped_voe_ptr<webrtc::VoEAudioProcessing> processing_;
|
||||
scoped_voe_ptr<webrtc::VoEBase> base_;
|
||||
scoped_voe_ptr<webrtc::VoECodec> codec_;
|
||||
scoped_voe_ptr<webrtc::VoEHardware> hw_;
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include "webrtc/media/base/audiosource.h"
|
||||
#include "webrtc/media/base/mediaconstants.h"
|
||||
#include "webrtc/media/base/streamparams.h"
|
||||
#include "webrtc/media/engine/apm_helpers.h"
|
||||
#include "webrtc/media/engine/payload_type_mapper.h"
|
||||
#include "webrtc/media/engine/webrtcmediaengine.h"
|
||||
#include "webrtc/media/engine/webrtcvoe.h"
|
||||
@ -40,6 +41,7 @@
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/system_wrappers/include/field_trial.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
#include "webrtc/voice_engine/transmit_mixer.h"
|
||||
|
||||
namespace cricket {
|
||||
namespace {
|
||||
@ -559,7 +561,7 @@ rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
|
||||
return rtc::Optional<int>(codec_rate);
|
||||
}
|
||||
|
||||
} // namespace {
|
||||
} // namespace
|
||||
|
||||
bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in,
|
||||
webrtc::CodecInst* out) {
|
||||
@ -620,10 +622,12 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(
|
||||
apm_ = voe_wrapper_->base()->audio_processing();
|
||||
RTC_DCHECK(apm_);
|
||||
|
||||
transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
|
||||
RTC_DCHECK(transmit_mixer_);
|
||||
|
||||
// Save the default AGC configuration settings. This must happen before
|
||||
// calling ApplyOptions or the default will be overwritten.
|
||||
int error = voe_wrapper_->processing()->GetAgcConfig(default_agc_config_);
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm_);
|
||||
|
||||
// Set default engine options.
|
||||
{
|
||||
@ -680,9 +684,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
|
||||
// kEcConference is AEC with high suppression.
|
||||
webrtc::EcModes ec_mode = webrtc::kEcConference;
|
||||
webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone;
|
||||
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
|
||||
webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
|
||||
if (options.aecm_generate_comfort_noise) {
|
||||
LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
|
||||
<< *options.aecm_generate_comfort_noise
|
||||
@ -729,8 +731,6 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
options.intelligibility_enhancer = rtc::Optional<bool>(false);
|
||||
#endif
|
||||
|
||||
webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing();
|
||||
|
||||
if (options.echo_cancellation) {
|
||||
// Check if platform supports built-in EC. Currently only supported on
|
||||
// Android and in combination with Java based audio layer.
|
||||
@ -751,26 +751,14 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
|
||||
}
|
||||
}
|
||||
if (voep->SetEcStatus(*options.echo_cancellation, ec_mode) == -1) {
|
||||
LOG_RTCERR2(SetEcStatus, *options.echo_cancellation, ec_mode);
|
||||
return false;
|
||||
} else {
|
||||
LOG(LS_INFO) << "Echo control set to " << *options.echo_cancellation
|
||||
<< " with mode " << ec_mode;
|
||||
}
|
||||
webrtc::apm_helpers::SetEcStatus(
|
||||
apm(), *options.echo_cancellation, ec_mode);
|
||||
#if !defined(ANDROID)
|
||||
// TODO(ajm): Remove the error return on Android from webrtc.
|
||||
if (voep->SetEcMetricsStatus(*options.echo_cancellation) == -1) {
|
||||
LOG_RTCERR1(SetEcMetricsStatus, *options.echo_cancellation);
|
||||
return false;
|
||||
}
|
||||
webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
|
||||
#endif
|
||||
if (ec_mode == webrtc::kEcAecm) {
|
||||
bool cn = options.aecm_generate_comfort_noise.value_or(false);
|
||||
if (voep->SetAecmMode(aecm_mode, cn) != 0) {
|
||||
LOG_RTCERR2(SetAecmMode, aecm_mode, cn);
|
||||
return false;
|
||||
}
|
||||
webrtc::apm_helpers::SetAecmMode(apm(), cn);
|
||||
}
|
||||
}
|
||||
|
||||
@ -785,17 +773,12 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
|
||||
}
|
||||
}
|
||||
if (voep->SetAgcStatus(*options.auto_gain_control, agc_mode) == -1) {
|
||||
LOG_RTCERR2(SetAgcStatus, *options.auto_gain_control, agc_mode);
|
||||
return false;
|
||||
} else {
|
||||
LOG(LS_INFO) << "Auto gain set to " << *options.auto_gain_control
|
||||
<< " with mode " << agc_mode;
|
||||
}
|
||||
webrtc::apm_helpers::SetAgcStatus(
|
||||
apm(), adm(), *options.auto_gain_control, agc_mode);
|
||||
}
|
||||
|
||||
if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
|
||||
options.tx_agc_limiter) {
|
||||
options.tx_agc_limiter || options.adjust_agc_delta) {
|
||||
// Override default_agc_config_. Generally, an unset option means "leave
|
||||
// the VoE bits alone" in this function, so we want whatever is set to be
|
||||
// stored as the new "default". If we didn't, then setting e.g.
|
||||
@ -811,13 +794,15 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
default_agc_config_.digitalCompressionGaindB);
|
||||
default_agc_config_.limiterEnable =
|
||||
options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
|
||||
if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) {
|
||||
LOG_RTCERR3(SetAgcConfig,
|
||||
default_agc_config_.targetLeveldBOv,
|
||||
default_agc_config_.digitalCompressionGaindB,
|
||||
default_agc_config_.limiterEnable);
|
||||
return false;
|
||||
|
||||
webrtc::AgcConfig config = default_agc_config_;
|
||||
if (options.adjust_agc_delta) {
|
||||
config.targetLeveldBOv -= *options.adjust_agc_delta;
|
||||
LOG(LS_INFO) << "Adjusting AGC level from default -"
|
||||
<< default_agc_config_.targetLeveldBOv << "dB to -"
|
||||
<< config.targetLeveldBOv << "dB";
|
||||
}
|
||||
webrtc::apm_helpers::SetAgcConfig(apm_, config);
|
||||
}
|
||||
|
||||
if (options.intelligibility_enhancer) {
|
||||
@ -840,22 +825,12 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
|
||||
}
|
||||
}
|
||||
if (voep->SetNsStatus(*options.noise_suppression, ns_mode) == -1) {
|
||||
LOG_RTCERR2(SetNsStatus, *options.noise_suppression, ns_mode);
|
||||
return false;
|
||||
} else {
|
||||
LOG(LS_INFO) << "Noise suppression set to " << *options.noise_suppression
|
||||
<< " with mode " << ns_mode;
|
||||
}
|
||||
webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
|
||||
}
|
||||
|
||||
if (options.stereo_swapping) {
|
||||
LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
|
||||
voep->EnableStereoChannelSwapping(*options.stereo_swapping);
|
||||
if (voep->IsStereoChannelSwappingEnabled() != *options.stereo_swapping) {
|
||||
LOG_RTCERR1(EnableStereoChannelSwapping, *options.stereo_swapping);
|
||||
return false;
|
||||
}
|
||||
transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
|
||||
}
|
||||
|
||||
if (options.audio_jitter_buffer_max_packets) {
|
||||
@ -874,17 +849,8 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
if (options.typing_detection) {
|
||||
LOG(LS_INFO) << "Typing detection is enabled? "
|
||||
<< *options.typing_detection;
|
||||
if (voep->SetTypingDetectionStatus(*options.typing_detection) == -1) {
|
||||
// In case of error, log the info and continue
|
||||
LOG_RTCERR1(SetTypingDetectionStatus, *options.typing_detection);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.adjust_agc_delta) {
|
||||
LOG(LS_INFO) << "Adjust agc delta is " << *options.adjust_agc_delta;
|
||||
if (!AdjustAgcLevel(*options.adjust_agc_delta)) {
|
||||
return false;
|
||||
}
|
||||
webrtc::apm_helpers::SetTypingDetectionStatus(
|
||||
apm(), *options.typing_detection);
|
||||
}
|
||||
|
||||
webrtc::Config config;
|
||||
@ -1067,25 +1033,6 @@ void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
|
||||
channels_.erase(it);
|
||||
}
|
||||
|
||||
// Adjusts the default AGC target level by the specified delta.
|
||||
// NB: If we start messing with other config fields, we'll want
|
||||
// to save the current webrtc::AgcConfig as well.
|
||||
bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
webrtc::AgcConfig config = default_agc_config_;
|
||||
config.targetLeveldBOv -= delta;
|
||||
|
||||
LOG(LS_INFO) << "Adjusting AGC level from default -"
|
||||
<< default_agc_config_.targetLeveldBOv << "dB to -"
|
||||
<< config.targetLeveldBOv << "dB";
|
||||
|
||||
if (voe_wrapper_->processing()->SetAgcConfig(config) == -1) {
|
||||
LOG_RTCERR1(SetAgcConfig, config.targetLeveldBOv);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
|
||||
int64_t max_size_bytes) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
@ -1148,6 +1095,12 @@ webrtc::AudioProcessing* WebRtcVoiceEngine::apm() {
|
||||
return apm_;
|
||||
}
|
||||
|
||||
webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(transmit_mixer_);
|
||||
return transmit_mixer_;
|
||||
}
|
||||
|
||||
AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const {
|
||||
PayloadTypeMapper mapper;
|
||||
AudioCodecs out;
|
||||
@ -1884,7 +1837,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
|
||||
it.second->RecreateAudioSendStream(audio_network_adatptor_config);
|
||||
}
|
||||
|
||||
LOG(LS_INFO) << "Set voice channel options. Current options: "
|
||||
LOG(LS_INFO) << "Set voice channel options. Current options: "
|
||||
<< options_.ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -30,6 +30,12 @@
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/pc/channel.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace voe {
|
||||
class TransmitMixer;
|
||||
} // namespace voe
|
||||
} // namespace webrtc
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class AudioDeviceModule;
|
||||
@ -75,10 +81,6 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
void RegisterChannel(WebRtcVoiceMediaChannel* channel);
|
||||
void UnregisterChannel(WebRtcVoiceMediaChannel* channel);
|
||||
|
||||
// Called by WebRtcVoiceMediaChannel to set a gain offset from
|
||||
// the default AGC target level.
|
||||
bool AdjustAgcLevel(int delta);
|
||||
|
||||
VoEWrapper* voe() { return voe_wrapper_.get(); }
|
||||
int GetLastEngineError();
|
||||
|
||||
@ -109,6 +111,7 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
int CreateVoEChannel();
|
||||
webrtc::AudioDeviceModule* adm();
|
||||
webrtc::AudioProcessing* apm();
|
||||
webrtc::voe::TransmitMixer* transmit_mixer();
|
||||
|
||||
AudioCodecs CollectRecvCodecs() const;
|
||||
|
||||
@ -120,6 +123,8 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory_;
|
||||
// Reference to the APM, owned by VoE.
|
||||
webrtc::AudioProcessing* apm_ = nullptr;
|
||||
// Reference to the TransmitMixer, owned by VoE.
|
||||
webrtc::voe::TransmitMixer* transmit_mixer_ = nullptr;
|
||||
// The primary instance of WebRtc VoiceEngine.
|
||||
std::unique_ptr<VoEWrapper> voe_wrapper_;
|
||||
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "webrtc/api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
#include "webrtc/base/arraysize.h"
|
||||
#include "webrtc/base/byteorder.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/safe_conversions.h"
|
||||
#include "webrtc/call/call.h"
|
||||
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
|
||||
@ -29,6 +28,8 @@
|
||||
#include "webrtc/modules/audio_processing/include/mock_audio_processing.h"
|
||||
#include "webrtc/pc/channel.h"
|
||||
#include "webrtc/test/field_trial.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/voice_engine/transmit_mixer.h"
|
||||
|
||||
using testing::Return;
|
||||
using testing::StrictMock;
|
||||
@ -58,14 +59,20 @@ constexpr int kRtpHistoryMs = 5000;
|
||||
class FakeVoEWrapper : public cricket::VoEWrapper {
|
||||
public:
|
||||
explicit FakeVoEWrapper(cricket::FakeWebRtcVoiceEngine* engine)
|
||||
: cricket::VoEWrapper(engine, // processing
|
||||
engine, // base
|
||||
: cricket::VoEWrapper(engine, // base
|
||||
engine, // codec
|
||||
engine, // hw
|
||||
engine) { // volume
|
||||
}
|
||||
};
|
||||
|
||||
class MockTransmitMixer : public webrtc::voe::TransmitMixer {
|
||||
public:
|
||||
MockTransmitMixer() = default;
|
||||
virtual ~MockTransmitMixer() = default;
|
||||
|
||||
MOCK_METHOD1(EnableStereoChannelSwapping, void(bool enable));
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Tests that our stub library "works".
|
||||
@ -76,11 +83,14 @@ TEST(WebRtcVoiceEngineTestStubLibrary, StartupShutdown) {
|
||||
EXPECT_CALL(adm, BuiltInAECIsAvailable()).WillOnce(Return(false));
|
||||
EXPECT_CALL(adm, BuiltInAGCIsAvailable()).WillOnce(Return(false));
|
||||
EXPECT_CALL(adm, BuiltInNSIsAvailable()).WillOnce(Return(false));
|
||||
EXPECT_CALL(adm, SetAGC(true)).WillOnce(Return(0));
|
||||
StrictMock<webrtc::test::MockAudioProcessing> apm;
|
||||
EXPECT_CALL(apm, ApplyConfig(testing::_));
|
||||
EXPECT_CALL(apm, SetExtraOptions(testing::_));
|
||||
EXPECT_CALL(apm, Initialize()).WillOnce(Return(0));
|
||||
cricket::FakeWebRtcVoiceEngine voe(&apm);
|
||||
StrictMock<MockTransmitMixer> transmit_mixer;
|
||||
EXPECT_CALL(transmit_mixer, EnableStereoChannelSwapping(false));
|
||||
cricket::FakeWebRtcVoiceEngine voe(&apm, &transmit_mixer);
|
||||
EXPECT_FALSE(voe.IsInited());
|
||||
{
|
||||
cricket::WebRtcVoiceEngine engine(
|
||||
@ -105,16 +115,35 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
WebRtcVoiceEngineTestFake() : WebRtcVoiceEngineTestFake("") {}
|
||||
|
||||
explicit WebRtcVoiceEngineTestFake(const char* field_trials)
|
||||
: call_(webrtc::Call::Config(&event_log_)), voe_(&apm_),
|
||||
: apm_gc_(*apm_.gain_control()), apm_ec_(*apm_.echo_cancellation()),
|
||||
apm_ns_(*apm_.noise_suppression()), apm_vd_(*apm_.voice_detection()),
|
||||
call_(webrtc::Call::Config(&event_log_)), voe_(&apm_, &transmit_mixer_),
|
||||
override_field_trials_(field_trials) {
|
||||
// AudioDeviceModule.
|
||||
EXPECT_CALL(adm_, AddRef()).WillOnce(Return(0));
|
||||
EXPECT_CALL(adm_, Release()).WillOnce(Return(0));
|
||||
EXPECT_CALL(adm_, BuiltInAECIsAvailable()).WillOnce(Return(false));
|
||||
EXPECT_CALL(adm_, BuiltInAGCIsAvailable()).WillOnce(Return(false));
|
||||
EXPECT_CALL(adm_, BuiltInNSIsAvailable()).WillOnce(Return(false));
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
// AudioProcessing.
|
||||
EXPECT_CALL(apm_, ApplyConfig(testing::_));
|
||||
EXPECT_CALL(apm_, SetExtraOptions(testing::_));
|
||||
EXPECT_CALL(apm_, Initialize()).WillOnce(Return(0));
|
||||
// Default Options.
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_vd_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(transmit_mixer_, EnableStereoChannelSwapping(false));
|
||||
// Init does not overwrite default AGC config.
|
||||
EXPECT_CALL(apm_gc_, target_level_dbfs()).WillOnce(Return(1));
|
||||
EXPECT_CALL(apm_gc_, compression_gain_db()).WillRepeatedly(Return(5));
|
||||
EXPECT_CALL(apm_gc_, is_limiter_enabled()).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(apm_gc_, set_target_level_dbfs(1)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, set_compression_gain_db(5)).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_gc_, enable_limiter(true)).WillRepeatedly(Return(0));
|
||||
// TODO(kwiberg): We should use a mock AudioDecoderFactory, but a bunch of
|
||||
// the tests here probe the specific set of codecs provided by the builtin
|
||||
// factory. Those tests should probably be moved elsewhere.
|
||||
@ -123,6 +152,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
new FakeVoEWrapper(&voe_)));
|
||||
send_parameters_.codecs.push_back(kPcmuCodec);
|
||||
recv_parameters_.codecs.push_back(kPcmuCodec);
|
||||
// Default Options.
|
||||
EXPECT_TRUE(IsHighPassFilterEnabled());
|
||||
}
|
||||
|
||||
bool SetupChannel() {
|
||||
@ -607,6 +638,11 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
protected:
|
||||
StrictMock<webrtc::test::MockAudioDeviceModule> adm_;
|
||||
StrictMock<webrtc::test::MockAudioProcessing> apm_;
|
||||
webrtc::test::MockGainControl& apm_gc_;
|
||||
webrtc::test::MockEchoCancellation& apm_ec_;
|
||||
webrtc::test::MockNoiseSuppression& apm_ns_;
|
||||
webrtc::test::MockVoiceDetection& apm_vd_;
|
||||
StrictMock<MockTransmitMixer> transmit_mixer_;
|
||||
webrtc::RtcEventLogNullImpl event_log_;
|
||||
cricket::FakeCall call_;
|
||||
cricket::FakeWebRtcVoiceEngine voe_;
|
||||
@ -2450,46 +2486,37 @@ TEST_F(WebRtcVoiceEngineTestFake, PlayoutWithMultipleStreams) {
|
||||
// and start sending on it.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, CodianSend) {
|
||||
EXPECT_TRUE(SetupSendStream());
|
||||
cricket::AudioOptions options_adjust_agc;
|
||||
options_adjust_agc.adjust_agc_delta = rtc::Optional<int>(-10);
|
||||
webrtc::AgcConfig agc_config;
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
send_parameters_.options = options_adjust_agc;
|
||||
send_parameters_.options.adjust_agc_delta = rtc::Optional<int>(-10);
|
||||
EXPECT_CALL(apm_gc_,
|
||||
set_target_level_dbfs(11)).Times(2).WillRepeatedly(Return(0));
|
||||
SetSendParameters(send_parameters_);
|
||||
SetSend(true);
|
||||
EXPECT_TRUE(GetSendStream(kSsrc1).IsSending());
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||
EXPECT_EQ(agc_config.targetLeveldBOv, 10); // level was attenuated
|
||||
SetSend(false);
|
||||
EXPECT_FALSE(GetSendStream(kSsrc1).IsSending());
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) {
|
||||
EXPECT_TRUE(SetupSendStream());
|
||||
EXPECT_CALL(adm_,
|
||||
BuiltInAGCIsAvailable()).Times(2).WillRepeatedly(Return(false));
|
||||
webrtc::AgcConfig agc_config;
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
EXPECT_CALL(adm_, SetAGC(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).Times(2).WillOnce(Return(0));
|
||||
send_parameters_.options.tx_agc_target_dbov = rtc::Optional<uint16_t>(3);
|
||||
send_parameters_.options.tx_agc_digital_compression_gain =
|
||||
rtc::Optional<uint16_t>(9);
|
||||
send_parameters_.options.tx_agc_limiter = rtc::Optional<bool>(true);
|
||||
send_parameters_.options.auto_gain_control = rtc::Optional<bool>(true);
|
||||
EXPECT_CALL(apm_gc_, set_target_level_dbfs(3)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, set_compression_gain_db(9)).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_gc_, enable_limiter(true)).WillRepeatedly(Return(0));
|
||||
SetSendParameters(send_parameters_);
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||
EXPECT_EQ(3, agc_config.targetLeveldBOv);
|
||||
EXPECT_EQ(9, agc_config.digitalCompressionGaindB);
|
||||
EXPECT_TRUE(agc_config.limiterEnable);
|
||||
|
||||
// Check interaction with adjust_agc_delta. Both should be respected, for
|
||||
// backwards compatibility.
|
||||
send_parameters_.options.adjust_agc_delta = rtc::Optional<int>(-10);
|
||||
EXPECT_CALL(apm_gc_, set_target_level_dbfs(13)).WillOnce(Return(0));
|
||||
SetSendParameters(send_parameters_);
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||
EXPECT_EQ(13, agc_config.targetLeveldBOv);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, SampleRatesViaOptions) {
|
||||
@ -2957,202 +2984,102 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
BuiltInAGCIsAvailable()).Times(4).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(adm_,
|
||||
BuiltInNSIsAvailable()).Times(2).WillRepeatedly(Return(false));
|
||||
bool ec_enabled;
|
||||
webrtc::EcModes ec_mode;
|
||||
webrtc::AecmModes aecm_mode;
|
||||
bool cng_enabled;
|
||||
bool agc_enabled;
|
||||
webrtc::AgcModes agc_mode;
|
||||
webrtc::AgcConfig agc_config;
|
||||
bool ns_enabled;
|
||||
webrtc::NsModes ns_mode;
|
||||
bool stereo_swapping_enabled;
|
||||
bool typing_detection_enabled;
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_FALSE(cng_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
EXPECT_TRUE(IsHighPassFilterEnabled());
|
||||
EXPECT_FALSE(stereo_swapping_enabled);
|
||||
EXPECT_TRUE(typing_detection_enabled);
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
|
||||
|
||||
EXPECT_EQ(50, voe_.GetNetEqCapacity());
|
||||
EXPECT_FALSE(voe_.GetNetEqFastAccelerate());
|
||||
|
||||
// Nothing set in AudioOptions, so everything should be as default.
|
||||
send_parameters_.options = cricket::AudioOptions();
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_FALSE(cng_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
EXPECT_TRUE(IsHighPassFilterEnabled());
|
||||
EXPECT_FALSE(stereo_swapping_enabled);
|
||||
EXPECT_TRUE(typing_detection_enabled);
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
|
||||
EXPECT_EQ(50, voe_.GetNetEqCapacity());
|
||||
EXPECT_FALSE(voe_.GetNetEqFastAccelerate());
|
||||
|
||||
// Turn echo cancellation off
|
||||
EXPECT_CALL(apm_ec_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(false)).WillOnce(Return(0));
|
||||
send_parameters_.options.echo_cancellation = rtc::Optional<bool>(false);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
EXPECT_FALSE(ec_enabled);
|
||||
|
||||
// Turn echo cancellation back on, with settings, and make sure
|
||||
// nothing else changed.
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
send_parameters_.options.echo_cancellation = rtc::Optional<bool>(true);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
EXPECT_TRUE(IsHighPassFilterEnabled());
|
||||
EXPECT_FALSE(stereo_swapping_enabled);
|
||||
EXPECT_TRUE(typing_detection_enabled);
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
|
||||
|
||||
// Turn on delay agnostic aec and make sure nothing change w.r.t. echo
|
||||
// control.
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
send_parameters_.options.delay_agnostic_aec = rtc::Optional<bool>(true);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
|
||||
// Turn off echo cancellation and delay agnostic aec.
|
||||
EXPECT_CALL(apm_ec_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(false)).WillOnce(Return(0));
|
||||
send_parameters_.options.delay_agnostic_aec = rtc::Optional<bool>(false);
|
||||
send_parameters_.options.extended_filter_aec = rtc::Optional<bool>(false);
|
||||
send_parameters_.options.echo_cancellation = rtc::Optional<bool>(false);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
EXPECT_FALSE(ec_enabled);
|
||||
|
||||
// Turning delay agnostic aec back on should also turn on echo cancellation.
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
send_parameters_.options.delay_agnostic_aec = rtc::Optional<bool>(true);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
|
||||
// Turn off AGC
|
||||
EXPECT_CALL(adm_, SetAGC(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(false)).WillOnce(Return(0));
|
||||
send_parameters_.options.auto_gain_control = rtc::Optional<bool>(false);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
EXPECT_FALSE(agc_enabled);
|
||||
|
||||
// Turn AGC back on
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
send_parameters_.options.auto_gain_control = rtc::Optional<bool>(true);
|
||||
send_parameters_.options.adjust_agc_delta = rtc::Optional<int>();
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
|
||||
// Turn off other options (and stereo swapping on).
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_vd_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(transmit_mixer_, EnableStereoChannelSwapping(true));
|
||||
send_parameters_.options.noise_suppression = rtc::Optional<bool>(false);
|
||||
send_parameters_.options.highpass_filter = rtc::Optional<bool>(false);
|
||||
send_parameters_.options.typing_detection = rtc::Optional<bool>(false);
|
||||
send_parameters_.options.stereo_swapping = rtc::Optional<bool>(true);
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_FALSE(ns_enabled);
|
||||
EXPECT_FALSE(IsHighPassFilterEnabled());
|
||||
EXPECT_FALSE(typing_detection_enabled);
|
||||
EXPECT_TRUE(stereo_swapping_enabled);
|
||||
|
||||
// Set options again to ensure it has no impact.
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_vd_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(transmit_mixer_, EnableStereoChannelSwapping(true));
|
||||
SetSendParameters(send_parameters_);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_EQ(webrtc::kEcConference, ec_mode);
|
||||
EXPECT_FALSE(ns_enabled);
|
||||
EXPECT_EQ(webrtc::kNsHighSuppression, ns_mode);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, DefaultOptions) {
|
||||
EXPECT_TRUE(SetupSendStream());
|
||||
|
||||
bool ec_enabled;
|
||||
webrtc::EcModes ec_mode;
|
||||
bool agc_enabled;
|
||||
webrtc::AgcModes agc_mode;
|
||||
bool ns_enabled;
|
||||
webrtc::NsModes ns_mode;
|
||||
bool stereo_swapping_enabled;
|
||||
bool typing_detection_enabled;
|
||||
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
EXPECT_TRUE(IsHighPassFilterEnabled());
|
||||
EXPECT_TRUE(typing_detection_enabled);
|
||||
EXPECT_FALSE(stereo_swapping_enabled);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, InitDoesNotOverwriteDefaultAgcConfig) {
|
||||
webrtc::AgcConfig set_config = {0};
|
||||
set_config.targetLeveldBOv = 3;
|
||||
set_config.digitalCompressionGaindB = 9;
|
||||
set_config.limiterEnable = true;
|
||||
EXPECT_EQ(0, voe_.SetAgcConfig(set_config));
|
||||
|
||||
webrtc::AgcConfig config = {0};
|
||||
EXPECT_EQ(0, voe_.GetAgcConfig(config));
|
||||
EXPECT_EQ(set_config.targetLeveldBOv, config.targetLeveldBOv);
|
||||
EXPECT_EQ(set_config.digitalCompressionGaindB,
|
||||
config.digitalCompressionGaindB);
|
||||
EXPECT_EQ(set_config.limiterEnable, config.limiterEnable);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
EXPECT_TRUE(SetupSendStream());
|
||||
EXPECT_CALL(adm_,
|
||||
BuiltInAECIsAvailable()).Times(9).WillRepeatedly(Return(false));
|
||||
BuiltInAECIsAvailable()).Times(8).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(adm_,
|
||||
BuiltInAGCIsAvailable()).Times(9).WillRepeatedly(Return(false));
|
||||
BuiltInAGCIsAvailable()).Times(8).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(adm_,
|
||||
BuiltInNSIsAvailable()).Times(9).WillRepeatedly(Return(false));
|
||||
BuiltInNSIsAvailable()).Times(8).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(adm_,
|
||||
RecordingIsInitialized()).Times(2).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(adm_, Recording()).Times(2).WillRepeatedly(Return(false));
|
||||
@ -3180,6 +3107,11 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
parameters_options_all.options.echo_cancellation = rtc::Optional<bool>(true);
|
||||
parameters_options_all.options.auto_gain_control = rtc::Optional<bool>(true);
|
||||
parameters_options_all.options.noise_suppression = rtc::Optional<bool>(true);
|
||||
EXPECT_CALL(adm_, SetAGC(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_TRUE(channel1->SetSendParameters(parameters_options_all));
|
||||
EXPECT_EQ(parameters_options_all.options, channel1->options());
|
||||
EXPECT_TRUE(channel2->SetSendParameters(parameters_options_all));
|
||||
@ -3189,6 +3121,11 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
cricket::AudioSendParameters parameters_options_no_ns = send_parameters_;
|
||||
parameters_options_no_ns.options.noise_suppression =
|
||||
rtc::Optional<bool>(false);
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel1->SetSendParameters(parameters_options_no_ns));
|
||||
cricket::AudioOptions expected_options = parameters_options_all.options;
|
||||
expected_options.echo_cancellation = rtc::Optional<bool>(true);
|
||||
@ -3200,64 +3137,55 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
cricket::AudioSendParameters parameters_options_no_agc = send_parameters_;
|
||||
parameters_options_no_agc.options.auto_gain_control =
|
||||
rtc::Optional<bool>(false);
|
||||
EXPECT_CALL(adm_, SetAGC(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel2->SetSendParameters(parameters_options_no_agc));
|
||||
expected_options.echo_cancellation = rtc::Optional<bool>(true);
|
||||
expected_options.auto_gain_control = rtc::Optional<bool>(false);
|
||||
expected_options.noise_suppression = rtc::Optional<bool>(true);
|
||||
EXPECT_EQ(expected_options, channel2->options());
|
||||
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel_->SetSendParameters(parameters_options_all));
|
||||
bool ec_enabled;
|
||||
webrtc::EcModes ec_mode;
|
||||
bool agc_enabled;
|
||||
webrtc::AgcModes agc_mode;
|
||||
bool ns_enabled;
|
||||
webrtc::NsModes ns_mode;
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
|
||||
EXPECT_CALL(adm_, SetAGC(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
channel1->SetSend(true);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_FALSE(ns_enabled);
|
||||
|
||||
EXPECT_CALL(adm_, SetAGC(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
channel2->SetSend(true);
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_FALSE(agc_enabled);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
|
||||
// Make sure settings take effect while we are sending.
|
||||
EXPECT_TRUE(channel_->SetSendParameters(parameters_options_all));
|
||||
EXPECT_CALL(apm_, ApplyConfig(testing::_));
|
||||
EXPECT_CALL(apm_, SetExtraOptions(testing::_));
|
||||
cricket::AudioSendParameters parameters_options_no_agc_nor_ns =
|
||||
send_parameters_;
|
||||
parameters_options_no_agc_nor_ns.options.auto_gain_control =
|
||||
rtc::Optional<bool>(false);
|
||||
parameters_options_no_agc_nor_ns.options.noise_suppression =
|
||||
rtc::Optional<bool>(false);
|
||||
channel2->SetSend(true);
|
||||
EXPECT_CALL(adm_, SetAGC(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ec_, enable_metrics(true)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_gc_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel2->SetSendParameters(parameters_options_no_agc_nor_ns));
|
||||
expected_options.echo_cancellation = rtc::Optional<bool>(true);
|
||||
expected_options.auto_gain_control = rtc::Optional<bool>(false);
|
||||
expected_options.noise_suppression = rtc::Optional<bool>(false);
|
||||
EXPECT_EQ(expected_options, channel2->options());
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_FALSE(agc_enabled);
|
||||
EXPECT_FALSE(ns_enabled);
|
||||
}
|
||||
|
||||
// This test verifies DSCP settings are properly applied on voice media channel.
|
||||
|
||||
@ -44,6 +44,9 @@ namespace webrtc {
|
||||
class AudioDeviceModule;
|
||||
class AudioProcessing;
|
||||
class AudioTransport;
|
||||
namespace voe {
|
||||
class TransmitMixer;
|
||||
} // namespace voe
|
||||
|
||||
// VoiceEngineObserver
|
||||
class WEBRTC_DLLEXPORT VoiceEngineObserver {
|
||||
@ -143,6 +146,10 @@ class WEBRTC_DLLEXPORT VoEBase {
|
||||
// Returns NULL before Init() is called.
|
||||
virtual AudioDeviceModule* audio_device_module() = 0;
|
||||
|
||||
// This method is WIP - DO NOT USE!
|
||||
// Returns NULL before Init() is called.
|
||||
virtual voe::TransmitMixer* transmit_mixer() = 0;
|
||||
|
||||
// Terminates all VoiceEngine functions and releases allocated resources.
|
||||
// Returns 0.
|
||||
virtual int Terminate() = 0;
|
||||
|
||||
@ -22,6 +22,7 @@ class AgcConfigTest : public AfterStreamingFixture {
|
||||
webrtc::AgcConfig default_agc_config_;
|
||||
};
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AgcConfigTest, HasCorrectDefaultConfiguration) {
|
||||
webrtc::AgcConfig agc_config;
|
||||
|
||||
@ -33,6 +34,7 @@ TEST_F(AgcConfigTest, HasCorrectDefaultConfiguration) {
|
||||
EXPECT_EQ(default_agc_config_.limiterEnable, agc_config.limiterEnable);
|
||||
}
|
||||
|
||||
// Not needed anymore - we're not returning errors anymore, just logging.
|
||||
TEST_F(AgcConfigTest, DealsWithInvalidParameters) {
|
||||
webrtc::AgcConfig agc_config = default_agc_config_;
|
||||
agc_config.digitalCompressionGaindB = 91;
|
||||
@ -47,6 +49,7 @@ TEST_F(AgcConfigTest, DealsWithInvalidParameters) {
|
||||
EXPECT_EQ(VE_APM_ERROR, voe_base_->LastError());
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AgcConfigTest, CanGetAndSetAgcStatus) {
|
||||
webrtc::AgcConfig agc_config;
|
||||
agc_config.digitalCompressionGaindB = 17;
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
class EcMetricsTest : public AfterStreamingFixture {
|
||||
};
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(EcMetricsTest, EcMetricsAreOnByDefault) {
|
||||
// AEC must be enabled fist.
|
||||
EXPECT_EQ(0, voe_apm_->SetEcStatus(true, webrtc::kEcAec));
|
||||
@ -22,6 +23,7 @@ TEST_F(EcMetricsTest, EcMetricsAreOnByDefault) {
|
||||
EXPECT_TRUE(enabled);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(EcMetricsTest, CanEnableAndDisableEcMetrics) {
|
||||
// AEC must be enabled fist.
|
||||
EXPECT_EQ(0, voe_apm_->SetEcStatus(true, webrtc::kEcAec));
|
||||
@ -35,6 +37,8 @@ TEST_F(EcMetricsTest, CanEnableAndDisableEcMetrics) {
|
||||
ASSERT_FALSE(ec_on);
|
||||
}
|
||||
|
||||
// TODO(solenberg): Do we have higher or lower level tests that verify metrics?
|
||||
// It's not the right test for this level.
|
||||
TEST_F(EcMetricsTest, ManualTestEcMetrics) {
|
||||
SwitchToManualMicrophone();
|
||||
|
||||
@ -63,6 +67,7 @@ TEST_F(EcMetricsTest, ManualTestEcMetrics) {
|
||||
EXPECT_EQ(0, voe_apm_->SetEcMetricsStatus(false));
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(EcMetricsTest, GetEcMetricsFailsIfEcNotEnabled) {
|
||||
int dummy = 0;
|
||||
EXPECT_EQ(0, voe_apm_->SetEcMetricsStatus(true));
|
||||
@ -70,6 +75,7 @@ TEST_F(EcMetricsTest, GetEcMetricsFailsIfEcNotEnabled) {
|
||||
EXPECT_EQ(VE_APM_ERROR, voe_base_->LastError());
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(EcMetricsTest, GetEcDelayMetricsFailsIfEcNotEnabled) {
|
||||
int dummy = 0;
|
||||
float dummy_f = 0;
|
||||
@ -78,6 +84,8 @@ TEST_F(EcMetricsTest, GetEcDelayMetricsFailsIfEcNotEnabled) {
|
||||
EXPECT_EQ(VE_APM_ERROR, voe_base_->LastError());
|
||||
}
|
||||
|
||||
// TODO(solenberg): Do we have higher or lower level tests that verify metrics?
|
||||
// It's not the right test for this level.
|
||||
TEST_F(EcMetricsTest, ManualVerifyEcDelayMetrics) {
|
||||
SwitchToManualMicrophone();
|
||||
TEST_LOG("Verify EC Delay metrics:");
|
||||
|
||||
@ -101,6 +101,7 @@ class AudioProcessingTest : public AfterStreamingFixture {
|
||||
|
||||
#if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID)
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, AgcIsOnByDefault) {
|
||||
bool agc_enabled = false;
|
||||
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
|
||||
@ -110,12 +111,14 @@ TEST_F(AudioProcessingTest, AgcIsOnByDefault) {
|
||||
EXPECT_EQ(webrtc::kAgcAdaptiveAnalog, agc_mode);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, CanEnableAgcWithAllModes) {
|
||||
TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital);
|
||||
TryEnablingAgcWithMode(webrtc::kAgcAdaptiveAnalog);
|
||||
TryEnablingAgcWithMode(webrtc::kAgcFixedDigital);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, EcIsDisabledAndAecIsDefaultEcMode) {
|
||||
bool ec_enabled = true;
|
||||
webrtc::EcModes ec_mode = webrtc::kEcDefault;
|
||||
@ -125,14 +128,17 @@ TEST_F(AudioProcessingTest, EcIsDisabledAndAecIsDefaultEcMode) {
|
||||
EXPECT_EQ(webrtc::kEcAec, ec_mode);
|
||||
}
|
||||
|
||||
// Not needed anymore - apm_helpers::SetEcStatus() doesn't take kEcAec.
|
||||
TEST_F(AudioProcessingTest, EnablingEcAecShouldEnableEcAec) {
|
||||
TryEnablingEcWithMode(webrtc::kEcAec, webrtc::kEcAec);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, EnablingEcConferenceShouldEnableEcAec) {
|
||||
TryEnablingEcWithMode(webrtc::kEcConference, webrtc::kEcAec);
|
||||
}
|
||||
|
||||
// Not needed anymore - apm_helpers::SetEcStatus() doesn't take kEcDefault.
|
||||
TEST_F(AudioProcessingTest, EcModeIsPreservedWhenEcIsTurnedOff) {
|
||||
TryEnablingEcWithMode(webrtc::kEcConference, webrtc::kEcAec);
|
||||
|
||||
@ -146,6 +152,7 @@ TEST_F(AudioProcessingTest, EcModeIsPreservedWhenEcIsTurnedOff) {
|
||||
EXPECT_EQ(webrtc::kEcAec, ec_mode);
|
||||
}
|
||||
|
||||
// Not needed anymore - apm_helpers::SetEcStatus() doesn't take kEcDefault.
|
||||
TEST_F(AudioProcessingTest, CanEnableAndDisableEcModeSeveralTimesInARow) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_EQ(0, voe_apm_->SetEcStatus(true));
|
||||
@ -162,11 +169,13 @@ TEST_F(AudioProcessingTest, CanEnableAndDisableEcModeSeveralTimesInARow) {
|
||||
|
||||
#endif // !WEBRTC_IOS && !WEBRTC_ANDROID
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, EnablingEcAecmShouldEnableEcAecm) {
|
||||
// This one apparently applies to Android and iPhone as well.
|
||||
TryEnablingEcWithMode(webrtc::kEcAecm, webrtc::kEcAecm);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, EcAecmModeIsEnabledAndSpeakerphoneByDefault) {
|
||||
bool cng_enabled = false;
|
||||
webrtc::AecmModes aecm_mode = webrtc::kAecmEarpiece;
|
||||
@ -177,6 +186,7 @@ TEST_F(AudioProcessingTest, EcAecmModeIsEnabledAndSpeakerphoneByDefault) {
|
||||
EXPECT_EQ(webrtc::kAecmSpeakerphone, aecm_mode);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, CanSetAecmMode) {
|
||||
EXPECT_EQ(0, voe_apm_->SetEcStatus(true, webrtc::kEcAecm));
|
||||
|
||||
@ -189,6 +199,7 @@ TEST_F(AudioProcessingTest, CanSetAecmMode) {
|
||||
TryEnablingAecmWithMode(webrtc::kAecmSpeakerphone, false);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, NsIsOffWithModerateSuppressionByDefault) {
|
||||
bool ns_status = true;
|
||||
webrtc::NsModes ns_mode = webrtc::kNsDefault;
|
||||
@ -198,6 +209,7 @@ TEST_F(AudioProcessingTest, NsIsOffWithModerateSuppressionByDefault) {
|
||||
EXPECT_EQ(webrtc::kNsModerateSuppression, ns_mode);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, CanSetNsMode) {
|
||||
// Concrete suppression values map to themselves.
|
||||
TryEnablingNsWithMode(webrtc::kNsHighSuppression,
|
||||
@ -216,6 +228,8 @@ TEST_F(AudioProcessingTest, CanSetNsMode) {
|
||||
webrtc::kNsModerateSuppression);
|
||||
}
|
||||
|
||||
// TODO(solenberg): Duplicate this test at the voe::Channel layer.
|
||||
// Not needed anymore - API is unused.
|
||||
TEST_F(AudioProcessingTest, VadIsDisabledByDefault) {
|
||||
bool vad_enabled;
|
||||
bool disabled_dtx;
|
||||
@ -227,6 +241,7 @@ TEST_F(AudioProcessingTest, VadIsDisabledByDefault) {
|
||||
EXPECT_FALSE(vad_enabled);
|
||||
}
|
||||
|
||||
// Not needed anymore - API is unused.
|
||||
TEST_F(AudioProcessingTest, VoiceActivityIndicatorReturns1WithSpeechOn) {
|
||||
// This sleep is necessary since the voice detection algorithm needs some
|
||||
// time to detect the speech from the fake microphone.
|
||||
@ -234,6 +249,7 @@ TEST_F(AudioProcessingTest, VoiceActivityIndicatorReturns1WithSpeechOn) {
|
||||
EXPECT_EQ(1, voe_apm_->VoiceActivityIndicator(channel_));
|
||||
}
|
||||
|
||||
// Not needed anymore - API is unused.
|
||||
TEST_F(AudioProcessingTest, CanSetDelayOffset) {
|
||||
voe_apm_->SetDelayOffsetMs(50);
|
||||
EXPECT_EQ(50, voe_apm_->DelayOffsetMs());
|
||||
@ -241,10 +257,13 @@ TEST_F(AudioProcessingTest, CanSetDelayOffset) {
|
||||
EXPECT_EQ(-50, voe_apm_->DelayOffsetMs());
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, HighPassFilterIsOnByDefault) {
|
||||
EXPECT_TRUE(voe_apm_->IsHighPassFilterEnabled());
|
||||
}
|
||||
|
||||
// TODO(solenberg): Check that sufficient testing is done in APM.
|
||||
// Not needed anymore - API is unused.
|
||||
TEST_F(AudioProcessingTest, CanSetHighPassFilter) {
|
||||
EXPECT_EQ(0, voe_apm_->EnableHighPassFilter(true));
|
||||
EXPECT_TRUE(voe_apm_->IsHighPassFilterEnabled());
|
||||
@ -252,10 +271,12 @@ TEST_F(AudioProcessingTest, CanSetHighPassFilter) {
|
||||
EXPECT_FALSE(voe_apm_->IsHighPassFilterEnabled());
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, StereoChannelSwappingIsOffByDefault) {
|
||||
EXPECT_FALSE(voe_apm_->IsStereoChannelSwappingEnabled());
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, CanSetStereoChannelSwapping) {
|
||||
voe_apm_->EnableStereoChannelSwapping(true);
|
||||
EXPECT_TRUE(voe_apm_->IsStereoChannelSwappingEnabled());
|
||||
@ -263,6 +284,7 @@ TEST_F(AudioProcessingTest, CanSetStereoChannelSwapping) {
|
||||
EXPECT_FALSE(voe_apm_->IsStereoChannelSwappingEnabled());
|
||||
}
|
||||
|
||||
// TODO(solenberg): Check that sufficient testing is done in APM.
|
||||
TEST_F(AudioProcessingTest, CanStartAndStopDebugRecording) {
|
||||
std::string output_path = webrtc::test::OutputPath();
|
||||
std::string output_file = output_path + "apm_debug.txt";
|
||||
@ -274,6 +296,7 @@ TEST_F(AudioProcessingTest, CanStartAndStopDebugRecording) {
|
||||
|
||||
#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, AgcIsOffByDefaultAndDigital) {
|
||||
bool agc_enabled = true;
|
||||
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
|
||||
@ -283,16 +306,19 @@ TEST_F(AudioProcessingTest, AgcIsOffByDefaultAndDigital) {
|
||||
EXPECT_EQ(webrtc::kAgcAdaptiveDigital, agc_mode);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, CanEnableAgcInAdaptiveDigitalMode) {
|
||||
TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital);
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, AgcIsPossibleExceptInAdaptiveAnalogMode) {
|
||||
EXPECT_EQ(-1, voe_apm_->SetAgcStatus(true, webrtc::kAgcAdaptiveAnalog));
|
||||
EXPECT_EQ(0, voe_apm_->SetAgcStatus(true, webrtc::kAgcFixedDigital));
|
||||
EXPECT_EQ(0, voe_apm_->SetAgcStatus(true, webrtc::kAgcAdaptiveDigital));
|
||||
}
|
||||
|
||||
// Duplicated in apm_helpers_unittest.cc.
|
||||
TEST_F(AudioProcessingTest, EcIsDisabledAndAecmIsDefaultEcMode) {
|
||||
bool ec_enabled = true;
|
||||
webrtc::EcModes ec_mode = webrtc::kEcDefault;
|
||||
@ -302,6 +328,7 @@ TEST_F(AudioProcessingTest, EcIsDisabledAndAecmIsDefaultEcMode) {
|
||||
EXPECT_EQ(webrtc::kEcAecm, ec_mode);
|
||||
}
|
||||
|
||||
// Not needed anymore - API is unused.
|
||||
TEST_F(AudioProcessingTest, TestVoiceActivityDetection) {
|
||||
TryDetectingSilence();
|
||||
TryDetectingSpeechAfterSilence();
|
||||
|
||||
@ -176,31 +176,12 @@ TransmitMixer::Destroy(TransmitMixer*& mixer)
|
||||
}
|
||||
|
||||
TransmitMixer::TransmitMixer(uint32_t instanceId) :
|
||||
_engineStatisticsPtr(NULL),
|
||||
_channelManagerPtr(NULL),
|
||||
audioproc_(NULL),
|
||||
_voiceEngineObserverPtr(NULL),
|
||||
_processThreadPtr(NULL),
|
||||
// Avoid conflict with other channels by adding 1024 - 1026,
|
||||
// won't use as much as 1024 channels.
|
||||
_filePlayerId(instanceId + 1024),
|
||||
_fileRecorderId(instanceId + 1025),
|
||||
_fileCallRecorderId(instanceId + 1026),
|
||||
_filePlaying(false),
|
||||
_fileRecording(false),
|
||||
_fileCallRecording(false),
|
||||
_audioLevel(),
|
||||
#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||
_typingNoiseWarningPending(false),
|
||||
_typingNoiseDetected(false),
|
||||
#endif
|
||||
_saturationWarning(false),
|
||||
_instanceId(instanceId),
|
||||
_mixFileWithMicrophone(false),
|
||||
_captureLevel(0),
|
||||
_mute(false),
|
||||
stereo_codec_(false),
|
||||
swap_stereo_channels_(false)
|
||||
_instanceId(instanceId)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
|
||||
"TransmitMixer::TransmitMixer() - ctor");
|
||||
|
||||
@ -138,15 +138,15 @@ public:
|
||||
|
||||
|
||||
// FileCallback
|
||||
void PlayNotification(int32_t id,
|
||||
uint32_t durationMs);
|
||||
void PlayNotification(const int32_t id,
|
||||
const uint32_t durationMs);
|
||||
|
||||
void RecordNotification(int32_t id,
|
||||
uint32_t durationMs);
|
||||
void RecordNotification(const int32_t id,
|
||||
const uint32_t durationMs);
|
||||
|
||||
void PlayFileEnded(int32_t id);
|
||||
void PlayFileEnded(const int32_t id);
|
||||
|
||||
void RecordFileEnded(int32_t id);
|
||||
void RecordFileEnded(const int32_t id);
|
||||
|
||||
#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||
// Typing detection
|
||||
@ -158,9 +158,13 @@ public:
|
||||
int typeEventDelay);
|
||||
#endif
|
||||
|
||||
void EnableStereoChannelSwapping(bool enable);
|
||||
// Virtual to allow mocking.
|
||||
virtual void EnableStereoChannelSwapping(bool enable);
|
||||
bool IsStereoChannelSwappingEnabled();
|
||||
|
||||
protected:
|
||||
TransmitMixer() = default;
|
||||
|
||||
private:
|
||||
TransmitMixer(uint32_t instanceId);
|
||||
|
||||
@ -185,11 +189,11 @@ private:
|
||||
#endif
|
||||
|
||||
// uses
|
||||
Statistics* _engineStatisticsPtr;
|
||||
ChannelManager* _channelManagerPtr;
|
||||
AudioProcessing* audioproc_;
|
||||
VoiceEngineObserver* _voiceEngineObserverPtr;
|
||||
ProcessThread* _processThreadPtr;
|
||||
Statistics* _engineStatisticsPtr = nullptr;
|
||||
ChannelManager* _channelManagerPtr = nullptr;
|
||||
AudioProcessing* audioproc_ = nullptr;
|
||||
VoiceEngineObserver* _voiceEngineObserverPtr = nullptr;
|
||||
ProcessThread* _processThreadPtr = nullptr;
|
||||
|
||||
// owns
|
||||
MonitorModule _monitorModule;
|
||||
@ -198,12 +202,12 @@ private:
|
||||
std::unique_ptr<FilePlayer> file_player_;
|
||||
std::unique_ptr<FileRecorder> file_recorder_;
|
||||
std::unique_ptr<FileRecorder> file_call_recorder_;
|
||||
int _filePlayerId;
|
||||
int _fileRecorderId;
|
||||
int _fileCallRecorderId;
|
||||
bool _filePlaying;
|
||||
bool _fileRecording;
|
||||
bool _fileCallRecording;
|
||||
int _filePlayerId = 0;
|
||||
int _fileRecorderId = 0;
|
||||
int _fileCallRecorderId = 0;
|
||||
bool _filePlaying = false;
|
||||
bool _fileRecording = false;
|
||||
bool _fileCallRecording = false;
|
||||
voe::AudioLevel _audioLevel;
|
||||
// protect file instances and their variables in MixedParticipants()
|
||||
rtc::CriticalSection _critSect;
|
||||
@ -211,21 +215,19 @@ private:
|
||||
|
||||
#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||
webrtc::TypingDetection _typingDetection;
|
||||
bool _typingNoiseWarningPending;
|
||||
bool _typingNoiseDetected;
|
||||
bool _typingNoiseWarningPending = false;
|
||||
bool _typingNoiseDetected = false;
|
||||
#endif
|
||||
bool _saturationWarning;
|
||||
bool _saturationWarning = false;
|
||||
|
||||
int _instanceId;
|
||||
bool _mixFileWithMicrophone;
|
||||
uint32_t _captureLevel;
|
||||
bool _mute;
|
||||
bool stereo_codec_;
|
||||
bool swap_stereo_channels_;
|
||||
int _instanceId = 0;
|
||||
bool _mixFileWithMicrophone = false;
|
||||
uint32_t _captureLevel = 0;
|
||||
bool _mute = false;
|
||||
bool stereo_codec_ = false;
|
||||
bool swap_stereo_channels_ = false;
|
||||
};
|
||||
|
||||
} // namespace voe
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_VOICE_ENGINE_TRANSMIT_MIXER_H
|
||||
|
||||
@ -38,6 +38,9 @@ class VoEBaseImpl : public VoEBase,
|
||||
AudioDeviceModule* audio_device_module() override {
|
||||
return shared_->audio_device();
|
||||
}
|
||||
voe::TransmitMixer* transmit_mixer() override {
|
||||
return shared_->transmit_mixer();
|
||||
}
|
||||
int Terminate() override;
|
||||
|
||||
int CreateChannel() override;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user