Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TWCC: Fix small receive delta rounding #207

Merged
merged 1 commit into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions pkg/twcc/twcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,16 @@ func (f *feedback) getRTCP() *rtcp.TransportLayerCC {

func (f *feedback) addReceived(sequenceNumber uint16, timestampUS int64) bool {
deltaUS := timestampUS - f.lastTimestampUS
delta250US := deltaUS / 250
var delta250US int64
if deltaUS >= 0 {
delta250US = (deltaUS + rtcp.TypeTCCDeltaScaleFactor/2) / rtcp.TypeTCCDeltaScaleFactor
} else {
delta250US = (deltaUS - rtcp.TypeTCCDeltaScaleFactor/2) / rtcp.TypeTCCDeltaScaleFactor
}
if delta250US < math.MinInt16 || delta250US > math.MaxInt16 { // delta doesn't fit into 16 bit, need to create new packet
return false
}
deltaUSRounded := delta250US * rtcp.TypeTCCDeltaScaleFactor

for ; f.nextSequenceNumber != sequenceNumber; f.nextSequenceNumber++ {
if !f.lastChunk.canAdd(rtcp.TypeTCCPacketNotReceived) {
Expand All @@ -183,9 +189,9 @@ func (f *feedback) addReceived(sequenceNumber uint16, timestampUS int64) bool {
f.lastChunk.add(recvDelta)
f.deltas = append(f.deltas, &rtcp.RecvDelta{
Type: recvDelta,
Delta: deltaUS,
Delta: deltaUSRounded,
})
f.lastTimestampUS = timestampUS
f.lastTimestampUS += deltaUSRounded
f.sequenceNumberCount++
f.nextSequenceNumber++
return true
Expand Down
47 changes: 47 additions & 0 deletions pkg/twcc/twcc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,53 @@ func Test_feedback(t *testing.T) {
}
})

t.Run("add received small deltas", func(t *testing.T) {
f := newFeedback(0, 0, 0)
base := int64(320 * 1000)
deltaUS := int64(200)
f.setBase(5, base)

for i := int64(0); i < 5; i++ {
kcaffrey marked this conversation as resolved.
Show resolved Hide resolved
got := f.addReceived(5+uint16(i+1), base+deltaUS*i)
assert.True(t, got)
}

pkt := f.getRTCP()

expectedDeltas := []*rtcp.RecvDelta{
{
Type: rtcp.TypeTCCPacketReceivedSmallDelta,
Delta: 0,
},
{
Type: rtcp.TypeTCCPacketReceivedSmallDelta,
// NOTE: The delta is less than the scale factor, but it should be rounded up.
// (rtcp.RecvDelta).Marshal() simply truncates to an interval of the scale factor,
// so we want to make sure that the deltas have any rounding applied when building
// the feedback.
Delta: 1 * rtcp.TypeTCCDeltaScaleFactor,
},
{
Type: rtcp.TypeTCCPacketReceivedSmallDelta,
Delta: 1 * rtcp.TypeTCCDeltaScaleFactor,
},
{
Type: rtcp.TypeTCCPacketReceivedSmallDelta,
// NOTE: This is zero because even though the deltas are all the same, the rounding error has
// built up enough by this packet to cause it to be rounded down.
Delta: 0 * rtcp.TypeTCCDeltaScaleFactor,
},
{
Type: rtcp.TypeTCCPacketReceivedSmallDelta,
Delta: 1 * rtcp.TypeTCCDeltaScaleFactor,
},
}
assert.Equal(t, len(expectedDeltas), len(pkt.RecvDeltas))
for i, d := range expectedDeltas {
assert.Equal(t, d, pkt.RecvDeltas[i])
}
})

t.Run("add received wrapped sequence number", func(t *testing.T) {
f := newFeedback(0, 0, 0)
f.setBase(65535, 320*1000)
Expand Down
Loading