diff --git a/go.mod b/go.mod index 8b996b883..df3c56d6b 100644 --- a/go.mod +++ b/go.mod @@ -27,14 +27,14 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/pion/dtls/v2 v2.2.6 github.com/pion/ice/v2 v2.3.2 - github.com/pion/interceptor v0.1.13 + github.com/pion/interceptor v0.1.16 github.com/pion/rtcp v1.2.10 github.com/pion/rtp v1.7.13 github.com/pion/sdp/v3 v3.0.6 github.com/pion/stun v0.4.0 github.com/pion/transport/v2 v2.2.0 github.com/pion/turn/v2 v2.1.0 - github.com/pion/webrtc/v3 v3.1.62 + github.com/pion/webrtc/v3 v3.2.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.15.0 github.com/redis/go-redis/v9 v9.0.3 @@ -80,7 +80,7 @@ require ( github.com/pion/logging v0.2.2 // indirect github.com/pion/mdns v0.0.7 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/sctp v1.8.6 // indirect + github.com/pion/sctp v1.8.7 // indirect github.com/pion/srtp/v2 v2.0.12 // indirect github.com/pion/udp/v2 v2.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 052a35a44..967527630 100644 --- a/go.sum +++ b/go.sum @@ -183,8 +183,8 @@ github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4= github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY= github.com/pion/ice/v2 v2.3.2 h1:vh+fi4RkZ8H5fB4brZ/jm3j4BqFgMmNs+aB3X52Hu7M= github.com/pion/ice/v2 v2.3.2/go.mod h1:AMIpuJqcpe+UwloocNebmTSWhCZM1TUCo9v7nW50jX0= -github.com/pion/interceptor v0.1.13 h1:tfJdEqPxnQrlstjd7SCL7B97WdjPkJtg5EpRMgJ61Ms= -github.com/pion/interceptor v0.1.13/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= +github.com/pion/interceptor v0.1.16 h1:0GDZrfNO+BmVNWymS31fMlVtPO2IJVBzy2Qq5XCYMIg= +github.com/pion/interceptor v0.1.16/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U= @@ -196,8 +196,8 @@ github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sctp v1.8.6 h1:CUex11Vkt9YS++VhLf8b55O3VqKrWL6W3SDwX4jAqsI= -github.com/pion/sctp v1.8.6/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= +github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw= +github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU= github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= github.com/pion/srtp/v2 v2.0.12 h1:WrmiVCubGMOAObBU1vwWjG0H3VSyQHawKeer2PVA5rY= @@ -208,14 +208,15 @@ github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40 github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= github.com/pion/transport/v2 v2.0.2/go.mod h1:vrz6bUbFr/cjdwbnxq8OdDDzHf7JJfGsIRkxfpZoTA0= +github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= github.com/pion/transport/v2 v2.2.0 h1:u5lFqFHkXLMXMzai8tixZDfVjb8eOjH35yCunhPeb1c= github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI= github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs= github.com/pion/udp/v2 v2.0.1 h1:xP0z6WNux1zWEjhC7onRA3EwwSliXqu1ElUZAQhUP54= github.com/pion/udp/v2 v2.0.1/go.mod h1:B7uvTMP00lzWdyMr/1PVZXtV3wpPIxBRd4Wl6AksXn8= -github.com/pion/webrtc/v3 v3.1.62 h1:B+QYCs+ajtRMJtC3nphzFWWjVoCorugOABu/JD0pJ3c= -github.com/pion/webrtc/v3 v3.1.62/go.mod h1:PaPsj1aigBfWK1jJRZPkWvdiPaAiJwAEMgDKXVO7NjI= +github.com/pion/webrtc/v3 v3.2.1 h1:eehbYzkM6xWoH3LXoIBnZTb4TOrjwmVzI78JO1+5kgQ= +github.com/pion/webrtc/v3 v3.2.1/go.mod h1:sQVqop5YhZezvKyyz6Nywvf15LhlXUWiXWdN5DV4zHs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/pkg/sfu/buffer/rtpstats.go b/pkg/sfu/buffer/rtpstats.go index 06417365e..887008cdb 100644 --- a/pkg/sfu/buffer/rtpstats.go +++ b/pkg/sfu/buffer/rtpstats.go @@ -124,6 +124,7 @@ type RTPStats struct { lastRR rtcp.ReceptionReport highestTS uint32 + tsCycles uint32 highestTime int64 lastTransit uint32 @@ -174,7 +175,9 @@ type RTPStats struct { rtt uint32 maxRtt uint32 - srDataExt *RTCPSenderReportDataExt + srDataExt *RTCPSenderReportDataExt + firstSenderReportNTP mediatransportutil.NtpTime + firstSenderReportRTP uint32 nextSnapshotId uint32 snapshots map[uint32]*Snapshot @@ -212,6 +215,7 @@ func (r *RTPStats) Seed(from *RTPStats) { r.lastRR = from.lastRR r.highestTS = from.highestTS + r.tsCycles = from.tsCycles r.highestTime = from.highestTime r.lastTransit = from.lastTransit @@ -270,6 +274,8 @@ func (r *RTPStats) Seed(from *RTPStats) { } else { r.srDataExt = nil } + r.firstSenderReportNTP = from.firstSenderReportNTP + r.firstSenderReportRTP = from.firstSenderReportRTP r.nextSnapshotId = from.nextSnapshotId for id, ss := range from.snapshots { @@ -334,6 +340,7 @@ func (r *RTPStats) Update(rtph *rtp.Header, payloadSize int, paddingSize int, pa r.extStartSN = uint32(rtph.SequenceNumber) r.cycles = 0 + r.tsCycles = 0 first = true @@ -400,6 +407,9 @@ func (r *RTPStats) Update(rtph *rtp.Header, payloadSize int, paddingSize int, pa r.cycles++ } r.highestSN = rtph.SequenceNumber + if rtph.Timestamp < r.highestTS && !first { + r.tsCycles++ + } r.highestTS = rtph.Timestamp r.highestTime = packetTime } @@ -706,6 +716,11 @@ func (r *RTPStats) SetRtcpSenderReportData(srData *RTCPSenderReportData) { // prevent against extreme case of anachronous sender reports if r.srDataExt != nil && r.srDataExt.SenderReportData.NTPTimestamp > srData.NTPTimestamp { + r.logger.Debugw( + "anachronous RTCP sender report", + "current", srData.NTPTimestamp.Time(), + "last", r.srDataExt.SenderReportData.NTPTimestamp.Time(), + ) return } @@ -750,8 +765,8 @@ func (r *RTPStats) GetRtcpSenderReportDataExt() *RTCPSenderReportDataExt { } func (r *RTPStats) GetRtcpSenderReport(ssrc uint32, srDataExt *RTCPSenderReportDataExt) *rtcp.SenderReport { - r.lock.RLock() - defer r.lock.RUnlock() + r.lock.Lock() + defer r.lock.Unlock() if !r.initialized { return nil @@ -782,6 +797,37 @@ func (r *RTPStats) GetRtcpSenderReport(ssrc uint32, srDataExt *RTCPSenderReportD nowRTP = srDataExt.SenderReportData.RTPTimestamp + uint32(now.Sub(smoothedLocalTimeOfLatestSenderReportNTP).Milliseconds()*int64(r.params.ClockRate)/1000) } + // TODO-REMOVE-AFTER-DEBUG + if r.firstSenderReportNTP == 0 { + r.firstSenderReportNTP = nowNTP + r.firstSenderReportRTP = nowRTP + } else { + highestTime := time.Unix(0, r.highestTime) + ntpTime := nowNTP.Time() + ntpDiff := ntpTime.Sub(highestTime) + rtpDiff := int32(nowRTP - r.highestTS) + rtpOffset := int32(nowRTP - r.highestTS - uint32(ntpDiff.Milliseconds()*int64(r.params.ClockRate)/1000)) + + timeSinceFirst := nowNTP.Time().Sub(r.firstSenderReportNTP.Time()) + rtpDiffSinceFirst := getExtTS(nowRTP, r.tsCycles) - getExtTS(r.firstSenderReportRTP, 0) + drift := int64(uint64(timeSinceFirst.Milliseconds()*int64(r.params.ClockRate)/1000) - rtpDiffSinceFirst) + driftTime := float64(drift) / float64(r.params.ClockRate) / 1000 + r.logger.Debugw( + "sender report", + "highestTS", r.highestTS, + "reportTS", nowRTP, + "rtpDiff", rtpDiff, + "highestTime", highestTime, + "reportTime", ntpTime, + "timeDiff", ntpDiff, + "rtpOffset", rtpOffset, + "timeSinceFirst", timeSinceFirst, + "rtpDiffSinceFirst", rtpDiffSinceFirst, + "drift", drift, + "driftTime(ms)", driftTime, + ) + } + return &rtcp.SenderReport{ SSRC: ssrc, NTPTime: uint64(nowNTP), @@ -1375,6 +1421,10 @@ func (r *RTPStats) getAndResetSnapshot(snapshotId uint32, override bool) (*Snaps // ---------------------------------- +func getExtTS(ts uint32, cycles uint32) uint64 { + return (uint64(cycles) << 32) | uint64(ts) +} + func AggregateRTPStats(statsList []*livekit.RTPStats) *livekit.RTPStats { if len(statsList) == 0 { return nil