Skip to content

Commit

Permalink
More fine grained filtering NACKs after a key frame. (#2159)
Browse files Browse the repository at this point in the history
* More fine grained filtering NACKs after a key frame.

There are applications with periodic key frame.
So, a packet lost before a key frame will not be retransmitted.
But, decoder could wait (jitter buffer, play out time) and cause
a stutter.

Idea behind disabling NACKs after key frame was another knob to
throttle retransmission bit rate. But, with spaced out retransmissions
and max retransmissions per sequence number, there are throttles.
This would provide more throttling, but affects some applications.
So, disabling filtering NACKs after a key frame.

Introducing another flag to disallow layers. This would still be quite
useful, i. e. under congestion the stream allocator would move the
target lower. But, because of congestion, higher layer would have lost
a bunch of packets. Client would NACK those. Retransmitting those higher
layer packets would congest the channel more. The new flag (default
enabled) would disallow higher layers retransmission. This was happening
before this change also, just splitting out the flag for more control.

* split flag
  • Loading branch information
boks1971 committed Oct 19, 2023
1 parent e461e9c commit 0d74771
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 17 deletions.
4 changes: 3 additions & 1 deletion pkg/sfu/buffer/rtpstats_receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,9 @@ func (r *RTPStatsReceiver) SetRtcpSenderReportData(srData *RTCPSenderReportData)
timeSinceFirst := srData.NTPTimestamp.Time().Sub(r.srFirst.NTPTimestamp.Time()).Seconds()
rtpDiffSinceFirst := srDataCopy.RTPTimestampExt - r.srFirst.RTPTimestampExt
calculatedClockRateFromFirst := float64(rtpDiffSinceFirst) / timeSinceFirst
if math.Abs(float64(r.params.ClockRate)-calculatedClockRateFromLast) > 0.2*float64(r.params.ClockRate) || math.Abs(float64(r.params.ClockRate)-calculatedClockRateFromFirst) > 0.2*float64(r.params.ClockRate) {

if (timeSinceLast > 0.2 && math.Abs(float64(r.params.ClockRate)-calculatedClockRateFromLast) > 0.2*float64(r.params.ClockRate)) ||
(timeSinceFirst > 0.2 && math.Abs(float64(r.params.ClockRate)-calculatedClockRateFromFirst) > 0.2*float64(r.params.ClockRate)) {
r.logger.Infow(
"clock rate skew",
"first", r.srFirst.ToString(),
Expand Down
27 changes: 14 additions & 13 deletions pkg/sfu/forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import (
// Forwarder
const (
FlagPauseOnDowngrade = true
FlagFilterRTX = true
FlagFilterRTX = false
FlagFilterRTXLayers = true
TransitionCostSpatial = 10

ResumeBehindThresholdSeconds = float64(0.2) // 200ms
Expand Down Expand Up @@ -1399,15 +1400,14 @@ func (f *Forwarder) CheckSync() (locked bool, layer int32) {
}

func (f *Forwarder) FilterRTX(nacks []uint16) (filtered []uint16, disallowedLayers [buffer.DefaultMaxLayerSpatial + 1]bool) {
if !FlagFilterRTX {
filtered = nacks
return
}

f.lock.RLock()
defer f.lock.RUnlock()

filtered = f.rtpMunger.FilterRTX(nacks)
if !FlagFilterRTX {
filtered = nacks
} else {
filtered = f.rtpMunger.FilterRTX(nacks)
}

//
// Curb RTX when deficient for two cases
Expand All @@ -1417,14 +1417,15 @@ func (f *Forwarder) FilterRTX(nacks []uint16) (filtered []uint16, disallowedLaye
//
// Without the curb, when congestion hits, RTX rate could be so high that it further congests the channel.
//
currentLayer := f.vls.GetCurrent()
targetLayer := f.vls.GetTarget()
for layer := int32(0); layer < buffer.DefaultMaxLayerSpatial+1; layer++ {
if f.isDeficientLocked() && (targetLayer.Spatial < currentLayer.Spatial || layer > currentLayer.Spatial) {
disallowedLayers[layer] = true
if FlagFilterRTXLayers {
currentLayer := f.vls.GetCurrent()
targetLayer := f.vls.GetTarget()
for layer := int32(0); layer < buffer.DefaultMaxLayerSpatial+1; layer++ {
if f.isDeficientLocked() && (targetLayer.Spatial < currentLayer.Spatial || layer > currentLayer.Spatial) {
disallowedLayers[layer] = true
}
}
}

return
}

Expand Down
5 changes: 2 additions & 3 deletions pkg/sfu/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,6 @@ func NewWebRTCReceiver(
isRED: IsRedCodec(track.Codec().MimeType),
}

w.streamTrackerManager = NewStreamTrackerManager(logger, trackInfo, w.isSVC, w.codec.ClockRate, trackersConfig)
w.streamTrackerManager.SetListener(w)

for _, opt := range opts {
w = opt(w)
}
Expand All @@ -235,6 +232,8 @@ func NewWebRTCReceiver(
})
w.connectionStats.Start(w.trackInfo)

w.streamTrackerManager = NewStreamTrackerManager(logger, trackInfo, w.isSVC, w.codec.ClockRate, trackersConfig)
w.streamTrackerManager.SetListener(w)
// SVC-TODO: Handle DD for non-SVC cases???
if w.isSVC {
for _, ext := range receiver.GetParameters().HeaderExtensions {
Expand Down

0 comments on commit 0d74771

Please sign in to comment.