From 582adda97cab2e891b28a4daf5202eee380bcb15 Mon Sep 17 00:00:00 2001 From: Raja Subramanian Date: Wed, 15 Mar 2023 13:27:27 +0530 Subject: [PATCH] Fix connection quality in constrained up stream (#1521) A few things 1. Have to use expected layer in upstream distance to desired. Using min(published, expected) means if expected is higher than published, it was not caught as a missed layer. 2. Forgot to remove layer transition update in one place. It was still constrained to screen share. This caused quality to not pick up after constraint is released. 3. Switching to max layer cannot be marked on max published. Same as point #1 above. Otherwise, dynacast would kick in and turn off highest layer. --- pkg/sfu/forwarder.go | 13 +++++++++---- pkg/sfu/receiver.go | 4 +--- pkg/sfu/streamtrackermanager.go | 15 ++++++++++----- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/pkg/sfu/forwarder.go b/pkg/sfu/forwarder.go index 1b0dea4a6..d75c890a7 100644 --- a/pkg/sfu/forwarder.go +++ b/pkg/sfu/forwarder.go @@ -1452,7 +1452,7 @@ func (f *Forwarder) getTranslationParamsVideo(extPkt *buffer.ExtPacket, layer in // if f.ddLayerSelector != nil { // f.ddLayerSelector.SelectLayer(f.currentLayers) // } - if f.currentLayers.Spatial >= f.maxLayers.Spatial || f.currentLayers.Spatial == f.maxPublishedLayer { + if f.currentLayers.Spatial >= f.maxLayers.Spatial { tp.isSwitchingToMaxLayer = true } } @@ -1517,10 +1517,9 @@ func (f *Forwarder) getTranslationParamsVideo(extPkt *buffer.ExtPacket, layer in if found { tp.isSwitchingToTargetLayer = true f.clearParkedLayers() - if f.currentLayers.Spatial >= f.maxLayers.Spatial || f.currentLayers.Spatial == f.maxPublishedLayer { + if f.currentLayers.Spatial >= f.maxLayers.Spatial { tp.isSwitchingToMaxLayer = true - // if maximum is attained, adjust target to enable fast path layer check in per-packet path f.logger.Infow( "reached max layer", "current", f.currentLayers, @@ -1531,6 +1530,9 @@ func (f *Forwarder) getTranslationParamsVideo(extPkt *buffer.ExtPacket, layer in "maxPublished", f.maxPublishedLayer, "feed", extPkt.Packet.SSRC, ) + } + + if f.currentLayers.Spatial >= f.maxLayers.Spatial || f.currentLayers.Spatial == f.maxPublishedLayer { f.targetLayers.Spatial = f.currentLayers.Spatial } } @@ -1551,8 +1553,11 @@ func (f *Forwarder) getTranslationParamsVideo(extPkt *buffer.ExtPacket, layer in ) f.currentLayers.Spatial = layer - if f.currentLayers.Spatial >= f.maxLayers.Spatial || f.currentLayers.Spatial == f.maxPublishedLayer { + if f.currentLayers.Spatial >= f.maxLayers.Spatial { tp.isSwitchingToMaxLayer = true + } + + if f.currentLayers.Spatial >= f.maxLayers.Spatial || f.currentLayers.Spatial == f.maxPublishedLayer { f.targetLayers.Spatial = layer } } diff --git a/pkg/sfu/receiver.go b/pkg/sfu/receiver.go index 58a3221f8..ae7493fc5 100644 --- a/pkg/sfu/receiver.go +++ b/pkg/sfu/receiver.go @@ -440,9 +440,7 @@ func (w *WebRTCReceiver) OnBitrateReport(availableLayers []int32, bitrates Bitra dt.UpTrackBitrateReport(availableLayers, bitrates) } - if w.trackInfo.Source == livekit.TrackSource_SCREEN_SHARE { - w.connectionStats.AddLayerTransition(w.streamTrackerManager.DistanceToDesired(), time.Now()) - } + w.connectionStats.AddLayerTransition(w.streamTrackerManager.DistanceToDesired(), time.Now()) } func (w *WebRTCReceiver) GetLayeredBitrate() ([]int32, Bitrates) { diff --git a/pkg/sfu/streamtrackermanager.go b/pkg/sfu/streamtrackermanager.go index d6c6ba63b..6fd9585f7 100644 --- a/pkg/sfu/streamtrackermanager.go +++ b/pkg/sfu/streamtrackermanager.go @@ -286,7 +286,7 @@ func (s *StreamTrackerManager) DistanceToDesired() float64 { s.lock.RLock() defer s.lock.RUnlock() - if s.paused { + if s.paused || s.maxExpectedLayer < 0 || s.maxTemporalLayerSeen < 0 { return 0 } @@ -306,13 +306,18 @@ done: } } - if !maxLayers.IsValid() || s.maxTemporalLayerSeen < 0 { - return 0.0 + adjustedMaxLayers := maxLayers + if !maxLayers.IsValid() { + adjustedMaxLayers = VideoLayers{Spatial: 0, Temporal: 0} } distance := - ((s.getMaxExpectedLayerLocked() - maxLayers.Spatial) * (s.maxTemporalLayerSeen + 1)) + - (s.maxTemporalLayerSeen - maxLayers.Temporal) + ((s.maxExpectedLayer - adjustedMaxLayers.Spatial) * (s.maxTemporalLayerSeen + 1)) + + (s.maxTemporalLayerSeen - adjustedMaxLayers.Temporal) + if !maxLayers.IsValid() { + distance++ + } + return float64(distance) / float64(s.maxTemporalLayerSeen+1) }