summaryrefslogtreecommitdiff
path: root/indra/llwebrtc
diff options
context:
space:
mode:
authorRoxie Linden <roxie@lindenlab.com>2024-03-30 22:03:59 -0700
committerRoxie Linden <roxie@lindenlab.com>2024-03-30 22:03:59 -0700
commit567180508f7279ffd8039d1e839a6ab4e8fe21e9 (patch)
treecfdf7b2303b4ed6ec3c674e50f18414ca74bef53 /indra/llwebrtc
parentb3bb3d2d5145aa981cefd77ba564aa082475a8af (diff)
parentcdae5ebc168d95a304b9905de7b66381723e402f (diff)
Merge branch 'roxie/webrtc-voice' of https://github.com/secondlife/viewer into roxie/webrtc-voice
Diffstat (limited to 'indra/llwebrtc')
-rw-r--r--indra/llwebrtc/llwebrtc.cpp98
-rw-r--r--indra/llwebrtc/llwebrtc.h46
-rw-r--r--indra/llwebrtc/llwebrtc_impl.h8
3 files changed, 119 insertions, 33 deletions
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index bba1e99e2d..a1e125a8f2 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -157,7 +157,6 @@ LLWebRTCImpl::LLWebRTCImpl() :
void LLWebRTCImpl::init()
{
- RTC_DCHECK(mPeerConnectionFactory);
mPlayoutDevice = 0;
mRecordingDevice = 0;
rtc::InitializeSSL();
@@ -222,12 +221,10 @@ void LLWebRTCImpl::init()
mPeerCustomProcessor = new LLCustomProcessor;
webrtc::AudioProcessingBuilder apb;
apb.SetCapturePostProcessing(std::unique_ptr<webrtc::CustomProcessing>(mPeerCustomProcessor));
- rtc::scoped_refptr<webrtc::AudioProcessing> apm = apb.Create();
+ mAudioProcessingModule = apb.Create();
- // TODO: wire some of these to the primary interface and ultimately
- // to the UI to allow user config.
webrtc::AudioProcessing::Config apm_config;
- apm_config.echo_canceller.enabled = true;
+ apm_config.echo_canceller.enabled = false;
apm_config.echo_canceller.mobile_mode = false;
apm_config.gain_controller1.enabled = true;
apm_config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
@@ -250,8 +247,8 @@ void LLWebRTCImpl::init()
processing_config.reverse_output_stream().set_num_channels(2);
processing_config.reverse_output_stream().set_sample_rate_hz(48000);
- apm->Initialize(processing_config);
- apm->ApplyConfig(apm_config);
+ mAudioProcessingModule->Initialize(processing_config);
+ mAudioProcessingModule->ApplyConfig(apm_config);
mPeerConnectionFactory = webrtc::CreatePeerConnectionFactory(mNetworkThread.get(),
mWorkerThread.get(),
@@ -262,7 +259,7 @@ void LLWebRTCImpl::init()
nullptr /* video_encoder_factory */,
nullptr /* video_decoder_factory */,
nullptr /* audio_mixer */,
- apm);
+ mAudioProcessingModule);
mWorkerThread->BlockingCall([this]() { mPeerDeviceModule->StartPlayout(); });
}
@@ -318,6 +315,49 @@ void LLWebRTCImpl::setRecording(bool recording)
});
}
+void LLWebRTCImpl::setAudioConfig(LLWebRTCDeviceInterface::AudioConfig config)
+{
+ webrtc::AudioProcessing::Config apm_config;
+ apm_config.echo_canceller.enabled = config.mEchoCancellation;
+ apm_config.echo_canceller.mobile_mode = false;
+ apm_config.gain_controller1.enabled = true;
+ apm_config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+ apm_config.gain_controller2.enabled = true;
+ apm_config.high_pass_filter.enabled = true;
+ apm_config.transient_suppression.enabled = true;
+ apm_config.pipeline.multi_channel_render = true;
+ apm_config.pipeline.multi_channel_capture = true;
+ apm_config.pipeline.multi_channel_capture = true;
+
+ switch (config.mNoiseSuppressionLevel)
+ {
+ case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_NONE:
+ apm_config.noise_suppression.enabled = false;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
+ break;
+ case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_LOW:
+ apm_config.noise_suppression.enabled = true;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
+ break;
+ case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_MODERATE:
+ apm_config.noise_suppression.enabled = true;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
+ break;
+ case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_HIGH:
+ apm_config.noise_suppression.enabled = true;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kHigh;
+ break;
+ case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_VERY_HIGH:
+ apm_config.noise_suppression.enabled = true;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh;
+ break;
+ default:
+ apm_config.noise_suppression.enabled = false;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
+ }
+ mAudioProcessingModule->ApplyConfig(apm_config);
+}
+
void LLWebRTCImpl::refreshDevices()
{
mWorkerThread->PostTask([this]() { updateDevices(); });
@@ -619,32 +659,36 @@ void LLWebRTCPeerConnectionImpl::unsetSignalingObserver(LLWebRTCSignalingObserve
}
}
-// TODO: Add initialization structure through which
-// stun and turn servers may be passed in from
-// the sim or login.
-bool LLWebRTCPeerConnectionImpl::initializeConnection()
+bool LLWebRTCPeerConnectionImpl::initializeConnection(LLWebRTCPeerConnectionInterface::InitOptions options)
{
RTC_DCHECK(!mPeerConnection);
mAnswerReceived = false;
mWebRTCImpl->PostSignalingTask(
- [this]()
+ [this, options]()
{
+ std::vector<LLWebRTCPeerConnectionInterface::InitOptions::IceServers> servers = options.mServers;
+ if(servers.empty())
+ {
+ LLWebRTCPeerConnectionInterface::InitOptions::IceServers ice_servers;
+ ice_servers.mUrls.push_back("stun:stun.l.google.com:19302");
+ ice_servers.mUrls.push_back("stun1:stun.l.google.com:19302");
+ ice_servers.mUrls.push_back("stun2:stun.l.google.com:19302");
+ ice_servers.mUrls.push_back("stun3:stun.l.google.com:19302");
+ ice_servers.mUrls.push_back("stun4:stun.l.google.com:19302");
+ }
+
webrtc::PeerConnectionInterface::RTCConfiguration config;
+ for (auto server : servers)
+ {
+ webrtc::PeerConnectionInterface::IceServer ice_server;
+ ice_server.urls = server.mUrls;
+ ice_server.username = server.mUserName;
+ ice_server.password = server.mPassword;
+ config.servers.push_back(ice_server);
+ }
+
config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
- webrtc::PeerConnectionInterface::IceServer server;
- server.uri = "stun:roxie-turn.staging.secondlife.io:3478";
- config.servers.push_back(server);
- server.uri = "stun:stun.l.google.com:19302";
- config.servers.push_back(server);
- server.uri = "stun:stun1.l.google.com:19302";
- config.servers.push_back(server);
- server.uri = "stun:stun2.l.google.com:19302";
- config.servers.push_back(server);
- server.uri = "stun:stun3.l.google.com:19302";
- config.servers.push_back(server);
- server.uri = "stun:stun4.l.google.com:19302";
- config.servers.push_back(server);
config.set_min_port(60000);
config.set_max_port(60100);
@@ -674,7 +718,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection()
cricket::AudioOptions audioOptions;
audioOptions.auto_gain_control = true;
- audioOptions.echo_cancellation = true; // incompatible with opus stereo
+ audioOptions.echo_cancellation = false; // incompatible with opus stereo
audioOptions.noise_suppression = true;
mLocalStream = mPeerConnectionFactory->CreateLocalMediaStream("SLStream");
diff --git a/indra/llwebrtc/llwebrtc.h b/indra/llwebrtc/llwebrtc.h
index be2e5cdf68..f3a33435c9 100644
--- a/indra/llwebrtc/llwebrtc.h
+++ b/indra/llwebrtc/llwebrtc.h
@@ -99,10 +99,32 @@ class LLWebRTCDevicesObserver
// to enumerate, set, and get notifications of changes
// for both capture (microphone) and render (speaker)
// devices.
+
class LLWebRTCDeviceInterface
{
public:
-
+ struct AudioConfig {
+
+ bool mAGC { true };
+
+ bool mEchoCancellation { true };
+
+ // TODO: The various levels of noise suppression are configured
+ // on the APM which would require setting config on the APM.
+ // We should pipe the various values through
+ // later.
+ typedef enum {
+ NOISE_SUPPRESSION_LEVEL_NONE = 0,
+ NOISE_SUPPRESSION_LEVEL_LOW,
+ NOISE_SUPPRESSION_LEVEL_MODERATE,
+ NOISE_SUPPRESSION_LEVEL_HIGH,
+ NOISE_SUPPRESSION_LEVEL_VERY_HIGH
+ } ENoiseSuppressionLevel;
+ ENoiseSuppressionLevel mNoiseSuppressionLevel { NOISE_SUPPRESSION_LEVEL_VERY_HIGH };
+ };
+
+ virtual void setAudioConfig(AudioConfig config) = 0;
+
// instructs webrtc to refresh the device list.
virtual void refreshDevices() = 0;
@@ -194,19 +216,35 @@ class LLWebRTCSignalingObserver
virtual void OnDataChannelReady(LLWebRTCDataInterface *data_interface) = 0;
};
-
// LLWebRTCPeerConnectionInterface representsd a connection to a peer,
// in most cases a Secondlife WebRTC server. This interface
// allows for management of this peer connection.
class LLWebRTCPeerConnectionInterface
{
public:
+
+ struct InitOptions
+ {
+ // equivalent of PeerConnectionInterface::IceServer
+ struct IceServers {
+ // Valid formats are described in RFC7064 and RFC7065.
+ // Urls should containe dns hostnames (not IP addresses)
+ // as the TLS certificate policy is 'secure.'
+ // and we do not currentply support TLS extensions.
+ std::vector<std::string> mUrls;
+ std::string mUserName;
+ std::string mPassword;
+ };
+
+ std::vector<IceServers> mServers;
+ };
+
+ virtual bool initializeConnection(InitOptions options = InitOptions()) = 0;
+ virtual bool shutdownConnection() = 0;
virtual void setSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
virtual void unsetSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
- virtual bool initializeConnection() = 0;
- virtual bool shutdownConnection() = 0;
virtual void AnswerAvailable(const std::string &sdp) = 0;
};
diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h
index 38810a29b5..32faf2516c 100644
--- a/indra/llwebrtc/llwebrtc_impl.h
+++ b/indra/llwebrtc/llwebrtc_impl.h
@@ -145,6 +145,8 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceS
// LLWebRTCDeviceInterface
//
+ void setAudioConfig(LLWebRTCDeviceInterface::AudioConfig config = LLWebRTCDeviceInterface::AudioConfig()) override;
+
void refreshDevices() override;
void setDevicesObserver(LLWebRTCDevicesObserver *observer) override;
@@ -227,6 +229,8 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceS
// The factory that allows creation of native webrtc PeerConnections.
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> mPeerConnectionFactory;
+
+ rtc::scoped_refptr<webrtc::AudioProcessing> mAudioProcessingModule;
// more native webrtc stuff
std::unique_ptr<webrtc::TaskQueueFactory> mTaskQueueFactory;
@@ -278,11 +282,11 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
//
// LLWebRTCPeerConnection
//
+ bool initializeConnection(InitOptions options = InitOptions()) override;
+ bool shutdownConnection() override;
void setSignalingObserver(LLWebRTCSignalingObserver *observer) override;
void unsetSignalingObserver(LLWebRTCSignalingObserver *observer) override;
- bool initializeConnection() override;
- bool shutdownConnection() override;
void AnswerAvailable(const std::string &sdp) override;
//