From 0480f99a8326a99e2ec6172cc49ae220cf5f1e76 Mon Sep 17 00:00:00 2001 From: Raja Subramanian Date: Tue, 26 Mar 2024 17:33:24 +0530 Subject: [PATCH] Tweak adaptation to increase in propagation delay. (#2598) * Tweak adaptation to increase in propagation delay. A couple of issues - RTCP Sender Reports rate will vary based on underying track bitrate. (at least in theory, not all entities will do it though, for example SFU does standard rate of one per three seconds irrespective of track bit rate). So, adapt the long term estimate of propagation delay delta based on spacing of reports. - Re-init of propagation delay to adapt to path change was taking the last value before the switch. But, that one value could have been an outlier and accepting it is not great. So, adapt spike time propagation delay in a smoother fashion to ensure that all values during spike contribute to the final value. * clean up --- pkg/sfu/buffer/rtpstats_receiver.go | 31 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/pkg/sfu/buffer/rtpstats_receiver.go b/pkg/sfu/buffer/rtpstats_receiver.go index 0a1b61a28..fcce8e411 100644 --- a/pkg/sfu/buffer/rtpstats_receiver.go +++ b/pkg/sfu/buffer/rtpstats_receiver.go @@ -41,6 +41,8 @@ const ( cPropagationDelayFallFactor = float64(0.95) cPropagationDelayRiseFactor = float64(0.05) + cPropagationDelaySpikeAdaptationFactor = float64(0.5) + // do not adapt to small OR large (outlier) changes cPropagationDelayDeltaThresholdMin = 5 * time.Millisecond cPropagationDelayDeltaThresholdMaxFactor = 2 @@ -51,7 +53,7 @@ const ( // A long term version of delta of propagation delay is maintained and delta propagation delay exceeding // a factor of the long term version is considered a sharp increase. That will trigger the start of the // path change condition and if it persists, propagation delay will be reset. - cPropagationDelayDeltaAdaptationFactor = float64(0.05) + cPropagationDelayDeltaMaxInterval = 10 * time.Second cPropagationDelayDeltaHighResetNumReports = 3 cPropagationDelayDeltaHighResetWait = 10 * time.Second ) @@ -83,6 +85,7 @@ type RTPStatsReceiver struct { longTermDeltaPropagationDelay time.Duration propagationDelayDeltaHighCount int propagationDelayDeltaHighStartTime time.Time + propagationDelaySpike time.Duration clockSkewCount int outOfOrderSsenderReportCount int @@ -370,11 +373,17 @@ func (r *RTPStatsReceiver) SetRtcpSenderReportData(srData *RTCPSenderReportData) "current", &srDataCopy, } } - initPropagationDelay := func(pd time.Duration) { - r.propagationDelay = pd - r.longTermDeltaPropagationDelay = 0 + resetDelta := func() { r.propagationDelayDeltaHighCount = 0 r.propagationDelayDeltaHighStartTime = time.Time{} + r.propagationDelaySpike = 0 + } + initPropagationDelay := func(pd time.Duration) { + r.propagationDelay = pd + + r.longTermDeltaPropagationDelay = 0 + + resetDelta() } ntpTime := srDataCopy.NTPTimestamp.Time() @@ -392,14 +401,18 @@ func (r *RTPStatsReceiver) SetRtcpSenderReportData(srData *RTCPSenderReportData) if r.propagationDelayDeltaHighStartTime.IsZero() { r.propagationDelayDeltaHighStartTime = time.Now() } + if r.propagationDelaySpike == 0 { + r.propagationDelaySpike = propagationDelay + } else { + r.propagationDelaySpike += time.Duration(cPropagationDelaySpikeAdaptationFactor * float64(propagationDelay-r.propagationDelaySpike)) + } if r.propagationDelayDeltaHighCount >= cPropagationDelayDeltaHighResetNumReports && time.Since(r.propagationDelayDeltaHighStartTime) >= cPropagationDelayDeltaHighResetWait { r.logger.Debugw("re-initializing propagation delay", append(getPropagationFields(), "newPropagationDelay", propagationDelay.String())...) - initPropagationDelay(propagationDelay) + initPropagationDelay(r.propagationDelaySpike) } } else { - r.propagationDelayDeltaHighCount = 0 - r.propagationDelayDeltaHighStartTime = time.Time{} + resetDelta() if deltaPropagationDelay.Abs() > cPropagationDelayDeltaThresholdMin { factor := cPropagationDelayFallFactor @@ -421,7 +434,9 @@ func (r *RTPStatsReceiver) SetRtcpSenderReportData(srData *RTCPSenderReportData) if r.longTermDeltaPropagationDelay == 0 { r.longTermDeltaPropagationDelay = deltaPropagationDelay } else { - r.longTermDeltaPropagationDelay += time.Duration(cPropagationDelayDeltaAdaptationFactor * float64(deltaPropagationDelay-r.longTermDeltaPropagationDelay)) + sinceLastReport := srDataCopy.NTPTimestamp.Time().Sub(r.srNewest.NTPTimestamp.Time()) + adaptationFactor := min(1.0, float64(sinceLastReport)/float64(cPropagationDelayDeltaMaxInterval)) + r.longTermDeltaPropagationDelay += time.Duration(adaptationFactor * float64(deltaPropagationDelay-r.longTermDeltaPropagationDelay)) } } // adjust receive time to estimated propagation delay