add Client.PacketNTP(), ServerSession.PacketNTP()

This commit is contained in:
aler9
2023-08-15 00:56:01 +02:00
parent 4ad57d6a75
commit bfef17b717
19 changed files with 704 additions and 263 deletions

View File

@@ -10,6 +10,13 @@ import (
"github.com/pion/rtp"
)
// seconds since 1st January 1900
// higher 32 bits are the integer part, lower 32 bits are the fractional part
func ntpTimeRTCPToGo(v uint64) time.Time {
nano := int64((v>>32)*1000000000+(v&0xFFFFFFFF)) - 2208988800*1000000000
return time.Unix(0, nano)
}
func randUint32() (uint32, error) {
var b [4]byte
_, err := rand.Read(b[:])
@@ -19,13 +26,12 @@ func randUint32() (uint32, error) {
return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]), nil
}
var timeNow = time.Now
// RTCPReceiver is a utility to generate RTCP receiver reports.
type RTCPReceiver struct {
period time.Duration
receiverSSRC uint32
clockRate float64
receiverSSRC uint32
period time.Duration
timeNow func() time.Time
writePacketRTCP func(rtcp.Packet)
mutex sync.Mutex
@@ -36,16 +42,17 @@ type RTCPReceiver struct {
lastSSRC uint32
lastSequenceNumber uint16
lastTimeRTP uint32
lastTimeNTP time.Time
lastTimeSystem time.Time
totalLost uint32
totalLostSinceReport uint32
totalSinceReport uint32
jitter float64
// data from RTCP packets
firstSenderReportReceived bool
lastSenderReportNTP uint32
lastSenderReportTime time.Time
firstSenderReportReceived bool
lastSenderReportTimeNTP uint64
lastSenderReportTimeRTP uint32
lastSenderReportTimeSystem time.Time
terminate chan struct{}
done chan struct{}
@@ -53,9 +60,10 @@ type RTCPReceiver struct {
// New allocates a RTCPReceiver.
func New(
period time.Duration,
receiverSSRC *uint32,
clockRate int,
receiverSSRC *uint32,
period time.Duration,
timeNow func() time.Time,
writePacketRTCP func(rtcp.Packet),
) (*RTCPReceiver, error) {
if receiverSSRC == nil {
@@ -66,10 +74,15 @@ func New(
receiverSSRC = &v
}
if timeNow == nil {
timeNow = time.Now
}
rr := &RTCPReceiver{
period: period,
receiverSSRC: *receiverSSRC,
clockRate: float64(clockRate),
receiverSSRC: *receiverSSRC,
period: period,
timeNow: timeNow,
writePacketRTCP: writePacketRTCP,
terminate: make(chan struct{}),
done: make(chan struct{}),
@@ -95,7 +108,7 @@ func (rr *RTCPReceiver) run() {
for {
select {
case <-t.C:
report := rr.report(timeNow())
report := rr.report()
if report != nil {
rr.writePacketRTCP(report)
}
@@ -106,14 +119,16 @@ func (rr *RTCPReceiver) run() {
}
}
func (rr *RTCPReceiver) report(ts time.Time) rtcp.Packet {
func (rr *RTCPReceiver) report() rtcp.Packet {
rr.mutex.Lock()
defer rr.mutex.Unlock()
if !rr.firstRTPPacketReceived || rr.clockRate == 0 {
if !rr.firstRTPPacketReceived {
return nil
}
system := rr.timeNow()
report := &rtcp.ReceiverReport{
SSRC: rr.receiverSSRC,
Reports: []rtcp.ReceptionReport{
@@ -131,12 +146,12 @@ func (rr *RTCPReceiver) report(ts time.Time) rtcp.Packet {
if rr.firstSenderReportReceived {
// middle 32 bits out of 64 in the NTP timestamp of last sender report
report.Reports[0].LastSenderReport = rr.lastSenderReportNTP
report.Reports[0].LastSenderReport = uint32(rr.lastSenderReportTimeNTP >> 16)
// delay, expressed in units of 1/65536 seconds, between
// receiving the last SR packet from source SSRC_n and sending this
// reception report block
report.Reports[0].Delay = uint32(ts.Sub(rr.lastSenderReportTime).Seconds() * 65536)
report.Reports[0].Delay = uint32(system.Sub(rr.lastSenderReportTimeSystem).Seconds() * 65536)
}
rr.totalLostSinceReport = 0
@@ -146,7 +161,7 @@ func (rr *RTCPReceiver) report(ts time.Time) rtcp.Packet {
}
// ProcessPacket extracts the needed data from RTP packets.
func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, ntp time.Time, ptsEqualsDTS bool) {
func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, system time.Time, ptsEqualsDTS bool) {
rr.mutex.Lock()
defer rr.mutex.Unlock()
@@ -160,7 +175,7 @@ func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, ntp time.Time, ptsEqualsD
if ptsEqualsDTS {
rr.timeInitialized = true
rr.lastTimeRTP = pkt.Timestamp
rr.lastTimeNTP = ntp
rr.lastTimeSystem = system
}
// subsequent packets
@@ -194,7 +209,7 @@ func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, ntp time.Time, ptsEqualsD
if rr.timeInitialized {
// update jitter
// https://tools.ietf.org/html/rfc3550#page-39
D := ntp.Sub(rr.lastTimeNTP).Seconds()*rr.clockRate -
D := system.Sub(rr.lastTimeSystem).Seconds()*rr.clockRate -
(float64(pkt.Timestamp) - float64(rr.lastTimeRTP))
if D < 0 {
D = -D
@@ -204,20 +219,21 @@ func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, ntp time.Time, ptsEqualsD
rr.timeInitialized = true
rr.lastTimeRTP = pkt.Timestamp
rr.lastTimeNTP = ntp
rr.lastTimeSystem = system
rr.lastSSRC = pkt.SSRC
}
}
}
// ProcessSenderReport extracts the needed data from RTCP sender reports.
func (rr *RTCPReceiver) ProcessSenderReport(sr *rtcp.SenderReport, ts time.Time) {
func (rr *RTCPReceiver) ProcessSenderReport(sr *rtcp.SenderReport, system time.Time) {
rr.mutex.Lock()
defer rr.mutex.Unlock()
rr.firstSenderReportReceived = true
rr.lastSenderReportNTP = uint32(sr.NTPTime >> 16)
rr.lastSenderReportTime = ts
rr.lastSenderReportTimeNTP = sr.NTPTime
rr.lastSenderReportTimeRTP = sr.RTPTime
rr.lastSenderReportTimeSystem = system
}
// LastSSRC returns the SSRC of the last RTP packet.
@@ -226,3 +242,18 @@ func (rr *RTCPReceiver) LastSSRC() (uint32, bool) {
defer rr.mutex.Unlock()
return rr.lastSSRC, rr.firstRTPPacketReceived
}
// PacketNTP returns the NTP timestamp of the packet.
func (rr *RTCPReceiver) PacketNTP(ts uint32) (time.Time, bool) {
rr.mutex.Lock()
defer rr.mutex.Unlock()
if !rr.firstSenderReportReceived {
return time.Time{}, false
}
timeDiff := int32(ts - rr.lastSenderReportTimeRTP)
timeDiffGo := (time.Duration(timeDiff) * time.Second) / time.Duration(rr.clockRate)
return ntpTimeRTCPToGo(rr.lastSenderReportTimeNTP).Add(timeDiffGo), true
}