mirror of
https://github.com/aler9/gortsplib
synced 2025-10-23 15:13:30 +08:00
add Client.PacketNTP(), ServerSession.PacketNTP()
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user