diff options
Diffstat (limited to 'indra/llwebrtc/llwebrtc.cpp')
| -rw-r--r-- | indra/llwebrtc/llwebrtc.cpp | 107 |
1 files changed, 96 insertions, 11 deletions
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index 7c2481a94c..589934fcce 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -749,12 +749,17 @@ void LLWebRTCImpl::intSetMute(bool mute, int delay_ms) { mPeerCustomProcessor->setGain(mMute ? 0.0f : mGain); } + + // Sequence counter to prevent race conditions from rapid requests to mute/unmute + static std::atomic<uint32_t> mute_sequence(0); + uint32_t current_sequence = ++mute_sequence; + if (mMute) { mWorkerThread->PostDelayedTask( - [this] + [this, current_sequence] { - if (mDeviceModule) + if (mDeviceModule && (current_sequence == mute_sequence.load())) { mDeviceModule->ForceStopRecording(); } @@ -764,9 +769,9 @@ void LLWebRTCImpl::intSetMute(bool mute, int delay_ms) else { mWorkerThread->PostTask( - [this] + [this, current_sequence] { - if (mDeviceModule) + if (mDeviceModule && (current_sequence == mute_sequence.load())) { mDeviceModule->InitRecording(); mDeviceModule->ForceStartRecording(); @@ -822,6 +827,8 @@ LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() : mPeerConnection(nullptr), mMute(MUTE_INITIAL), mAnswerReceived(false), + mPeerConnectionState(webrtc::PeerConnectionInterface::PeerConnectionState::kNew), + mDisconnectCount(0), mPendingJobs(0) { } @@ -830,6 +837,7 @@ LLWebRTCPeerConnectionImpl::~LLWebRTCPeerConnectionImpl() { mSignalingObserverList.clear(); mDataObserverList.clear(); + mPeerConnectionFactory.release(); if (mPendingJobs > 0) { RTC_LOG(LS_ERROR) << __FUNCTION__ << "Destroying a connection that has " << std::to_string(mPendingJobs) << " unfinished jobs that might cause workers to crash"; @@ -893,7 +901,6 @@ void LLWebRTCPeerConnectionImpl::terminate() } mPendingJobs--; }); - mPeerConnectionFactory.release(); } void LLWebRTCPeerConnectionImpl::setSignalingObserver(LLWebRTCSignalingObserver *observer) { mSignalingObserverList.emplace_back(observer); } @@ -936,14 +943,17 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti config.set_max_port(60100); webrtc::PeerConnectionDependencies pc_dependencies(this); - if (mPeerConnectionFactory == nullptr) + // Other thread manages mPeerConnectionFactory's lifetime and it can be reset + // at any momment, create own scoped_refptr (atomic). + webrtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory = mPeerConnectionFactory; + if (peer_connection_factory == nullptr) { RTC_LOG(LS_ERROR) << __FUNCTION__ << "Error creating peer connection, factory doesn't exist"; // Too early? mPendingJobs--; return; } - auto error_or_peer_connection = mPeerConnectionFactory->CreatePeerConnectionOrError(config, std::move(pc_dependencies)); + auto error_or_peer_connection = peer_connection_factory->CreatePeerConnectionOrError(config, std::move(pc_dependencies)); if (error_or_peer_connection.ok()) { mPeerConnection = std::move(error_or_peer_connection.value()); @@ -976,10 +986,10 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti audioOptions.noise_suppression = true; audioOptions.init_recording_on_send = false; - mLocalStream = mPeerConnectionFactory->CreateLocalMediaStream("SLStream"); + mLocalStream = peer_connection_factory->CreateLocalMediaStream("SLStream"); webrtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track( - mPeerConnectionFactory->CreateAudioTrack("SLAudio", mPeerConnectionFactory->CreateAudioSource(audioOptions).get())); + peer_connection_factory->CreateAudioTrack("SLAudio", peer_connection_factory->CreateAudioSource(audioOptions).get())); audio_track->set_enabled(false); mLocalStream->AddTrack(audio_track); @@ -1017,6 +1027,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti } webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions; + this->AddRef(); // CreateOffer will deref this when it's done. Without this, the callbacks never get called. mPeerConnection->CreateOffer(this, offerOptions); mPendingJobs--; }); @@ -1244,11 +1255,15 @@ void LLWebRTCPeerConnectionImpl::OnIceGatheringChange(webrtc::PeerConnectionInte } } +static const webrtc::TimeDelta DISCONNECT_RENEGOTIATE_DELAY = webrtc::TimeDelta::Millis(10000); + // Called any time the PeerConnectionState changes. void LLWebRTCPeerConnectionImpl::OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) { RTC_LOG(LS_ERROR) << __FUNCTION__ << " Peer Connection State Change " << new_state; + mPeerConnectionState = new_state; + switch (new_state) { case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected: @@ -1264,13 +1279,32 @@ void LLWebRTCPeerConnectionImpl::OnConnectionChange(webrtc::PeerConnectionInterf break; } case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed: - case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected: { for (auto &observer : mSignalingObserverList) { observer->OnRenegotiationNeeded(); } - + break; + } + case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected: + { + // Wait 10 seconds before renegotiating in case the connection recovers on its own. + // Use a sequence count so that only the most recent disconnect transition can trigger + // a renegotiation, avoiding stale delayed tasks from earlier disconnect/reconnect cycles. + uint32_t disconnect_count = ++mDisconnectCount; + mWebRTCImpl->PostDelayedSignalingTask( + [this, disconnect_count]() + { + if (disconnect_count == mDisconnectCount + && mPeerConnectionState == webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected) + { + for (auto &observer : mSignalingObserverList) + { + observer->OnRenegotiationNeeded(); + } + } + }, + DISCONNECT_RENEGOTIATE_DELAY); break; } default: @@ -1543,6 +1577,57 @@ void LLWebRTCPeerConnectionImpl::unsetDataObserver(LLWebRTCDataObserver* observe } } +class LLStatsCollectorCallback : public webrtc::RTCStatsCollectorCallback +{ +public: + typedef std::function<void(const LLWebRTCStatsMap&)> StatsCallback; + + LLStatsCollectorCallback(StatsCallback callback) : callback_(callback) {} + + void OnStatsDelivered(const webrtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override + { + if (callback_) + { + // Transform RTCStatsReport stats to simple map + LLWebRTCStatsMap stats_map; + for (const auto& stats : *report) + { + std::map<std::string, std::string> stat_attributes; + + // Convert each attribute to string format + for (const auto& attribute : stats.Attributes()) + { + stat_attributes[attribute.name()] = attribute.ToString(); + } + stats_map[stats.id()] = stat_attributes; + } + callback_(stats_map); + } + } + +private: + StatsCallback callback_; +}; + +void LLWebRTCPeerConnectionImpl::gatherConnectionStats() +{ + if (!mPeerConnection) + { + return; + } + + auto stats_callback = webrtc::make_ref_counted<LLStatsCollectorCallback>( + [this](const LLWebRTCStatsMap& generic_stats) + { + for (auto& observer : mSignalingObserverList) + { + observer->OnStatsDelivered(generic_stats); + } + }); + + mPeerConnection->GetStats(stats_callback.get()); +} + LLWebRTCImpl * gWebRTCImpl = nullptr; LLWebRTCDeviceInterface * getDeviceInterface() { |
