diff --git a/go.mod b/go.mod index 4d746e13..8d29fe3e 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/asticode/go-astits v1.14.0 github.com/bluenviron/gohlslib/v2 v2.2.3 github.com/bluenviron/gortmplib v0.1.1 - github.com/bluenviron/gortsplib/v5 v5.1.2-0.20251026101219-59474a8fa3ab + github.com/bluenviron/gortsplib/v5 v5.1.2-0.20251112170709-0e56f305d197 github.com/bluenviron/mediacommon/v2 v2.5.1 github.com/datarhei/gosrt v0.9.0 github.com/fsnotify/fsnotify v1.9.0 @@ -36,7 +36,7 @@ require ( github.com/pion/transport/v3 v3.1.1 github.com/pion/webrtc/v4 v4.1.6 github.com/stretchr/testify v1.11.1 - golang.org/x/crypto v0.43.0 + golang.org/x/crypto v0.44.0 golang.org/x/sys v0.38.0 golang.org/x/term v0.37.0 gopkg.in/yaml.v2 v2.4.0 @@ -96,9 +96,9 @@ require ( go.uber.org/mock v0.5.0 // indirect golang.org/x/arch v0.20.0 // indirect golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.46.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/sync v0.18.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.38.0 // indirect google.golang.org/protobuf v1.36.9 // indirect diff --git a/go.sum b/go.sum index ddf692cc..2d0fa5fb 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/bluenviron/gohlslib/v2 v2.2.3 h1:1R/Jnh1kNR9UB09KAX6xjS2GcdKFRLuPd9wM github.com/bluenviron/gohlslib/v2 v2.2.3/go.mod h1:z4Viks+Mdgcl7OcOVJ1fgSmuUwCCJBxYJPLN49n7Vnw= github.com/bluenviron/gortmplib v0.1.1 h1:pmR6qfPcJJmE17lWQ/bpuBFZtgGnMrN8KdFj1Gl/ZoQ= github.com/bluenviron/gortmplib v0.1.1/go.mod h1:XWy2YzbTP1XEEZ8232OG7I1MSwubsbDRKDNhXGgS2kg= -github.com/bluenviron/gortsplib/v5 v5.1.2-0.20251026101219-59474a8fa3ab h1:9QH6j4y2FMo299Rz/hX5jrhI+THhWgZ/oSiEmwSPavk= -github.com/bluenviron/gortsplib/v5 v5.1.2-0.20251026101219-59474a8fa3ab/go.mod h1:+4E4JNF7dpDu8LgssZu9fB3Ndh6FNbvGYMKOKR/wvvI= +github.com/bluenviron/gortsplib/v5 v5.1.2-0.20251112170709-0e56f305d197 h1:NvBCxleaHdQwxZLpck4JwsOFYupbtg9+QnWnvRD2CYc= +github.com/bluenviron/gortsplib/v5 v5.1.2-0.20251112170709-0e56f305d197/go.mod h1:IPHhCqTQvmKZ9t101dfnsf8xvVHM2oGGmxxEH8KMof4= github.com/bluenviron/mediacommon/v2 v2.5.1 h1:qB2fb5c0xyl5OB2gfSfulpEJn7Cdm3vI2n8wjiLMxKI= github.com/bluenviron/mediacommon/v2 v2.5.1/go.mod h1:zy1fODPuS/kBd93ftgJS1Jhvjq7LFWfAo32KP7By9AE= github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= @@ -239,16 +239,16 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -270,8 +270,8 @@ golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/protocols/webrtc/incoming_track.go b/internal/protocols/webrtc/incoming_track.go index 8cb4dbe2..6cdef34c 100644 --- a/internal/protocols/webrtc/incoming_track.go +++ b/internal/protocols/webrtc/incoming_track.go @@ -1,7 +1,6 @@ package webrtc import ( - "sync/atomic" "time" "github.com/bluenviron/gortsplib/v5/pkg/rtpreceiver" @@ -239,12 +238,10 @@ var incomingAudioCodecs = []webrtc.RTPCodecParameters{ type IncomingTrack struct { OnPacketRTP func(*rtp.Packet) - track *webrtc.TrackRemote - receiver *webrtc.RTPReceiver - writeRTCP func([]rtcp.Packet) error - log logger.Writer - rtpPacketsReceived *uint64 - rtpPacketsLost *uint64 + track *webrtc.TrackRemote + receiver *webrtc.RTPReceiver + writeRTCP func([]rtcp.Packet) error + log logger.Writer packetsLost *counterdumper.CounterDumper rtpReceiver *rtpreceiver.Receiver @@ -347,19 +344,13 @@ func (t *IncomingTrack) start() { return } - packets, lost, err2 := t.rtpReceiver.ProcessPacket(pkt, time.Now(), true) - if err2 != nil { - t.log.Log(logger.Warn, err2.Error()) - continue - } + packets, lost := t.rtpReceiver.ProcessPacket2(pkt, time.Now(), true) + if lost != 0 { - atomic.AddUint64(t.rtpPacketsLost, lost) t.packetsLost.Add(lost) // do not return } - atomic.AddUint64(t.rtpPacketsReceived, uint64(len(packets))) - for _, pkt := range packets { // sometimes Chrome sends empty RTP packets. ignore them. if len(pkt.Payload) == 0 { diff --git a/internal/protocols/webrtc/outgoing_track.go b/internal/protocols/webrtc/outgoing_track.go index 075280ff..fad9c1dd 100644 --- a/internal/protocols/webrtc/outgoing_track.go +++ b/internal/protocols/webrtc/outgoing_track.go @@ -2,7 +2,6 @@ package webrtc import ( "strings" - "sync/atomic" "time" "github.com/bluenviron/gortsplib/v5/pkg/rtpsender" @@ -15,10 +14,9 @@ import ( type OutgoingTrack struct { Caps webrtc.RTPCodecCapability - track *webrtc.TrackLocalStaticRTP - ssrc uint32 - rtcpSender *rtpsender.Sender - rtpPacketsSent *uint64 + track *webrtc.TrackLocalStaticRTP + ssrc uint32 + rtcpSender *rtpsender.Sender } func (t *OutgoingTrack) isVideo() bool { @@ -60,8 +58,6 @@ func (t *OutgoingTrack) setup(p *PeerConnection) error { } t.rtcpSender.Initialize() - t.rtpPacketsSent = p.rtpPacketsSent - // incoming RTCP packets must always be read to make interceptors work go func() { buf := make([]byte, 1500) @@ -99,7 +95,5 @@ func (t *OutgoingTrack) WriteRTPWithNTP(pkt *rtp.Packet, ntp time.Time) error { t.rtcpSender.ProcessPacket(pkt, ntp, true) - atomic.AddUint64(t.rtpPacketsSent, 1) - return t.track.WriteRTP(pkt) } diff --git a/internal/protocols/webrtc/peer_connection.go b/internal/protocols/webrtc/peer_connection.go index 7b34037e..b43f26be 100644 --- a/internal/protocols/webrtc/peer_connection.go +++ b/internal/protocols/webrtc/peer_connection.go @@ -147,15 +147,12 @@ type PeerConnection struct { OutgoingTracks []*OutgoingTrack Log logger.Writer - wr *webrtc.PeerConnection - ctx context.Context - ctxCancel context.CancelFunc - incomingTracks []*IncomingTrack - startedReading *int64 - rtpPacketsReceived *uint64 - rtpPacketsSent *uint64 - rtpPacketsLost *uint64 - statsInterceptor *statsInterceptor + wr *webrtc.PeerConnection + ctx context.Context + ctxCancel context.CancelFunc + incomingTracks []*IncomingTrack + startedReading *int64 + statsInterceptor *statsInterceptor newLocalCandidate chan *webrtc.ICECandidateInit incomingTrack chan trackRecvPair @@ -303,9 +300,6 @@ func (co *PeerConnection) Start() error { co.ctx, co.ctxCancel = context.WithCancel(context.Background()) co.startedReading = new(int64) - co.rtpPacketsReceived = new(uint64) - co.rtpPacketsSent = new(uint64) - co.rtpPacketsLost = new(uint64) co.newLocalCandidate = make(chan *webrtc.ICECandidateInit) co.connected = make(chan struct{}) @@ -707,12 +701,10 @@ func (co *PeerConnection) GatherIncomingTracks() error { case pair := <-co.incomingTrack: t := &IncomingTrack{ - track: pair.track, - receiver: pair.receiver, - writeRTCP: co.wr.WriteRTCP, - log: co.Log, - rtpPacketsReceived: co.rtpPacketsReceived, - rtpPacketsLost: co.rtpPacketsLost, + track: pair.track, + receiver: pair.receiver, + writeRTCP: co.wr.WriteRTCP, + log: co.Log, } t.initialize() co.incomingTracks = append(co.incomingTracks, t) @@ -810,16 +802,27 @@ func (co *PeerConnection) Stats() *Stats { v := float64(0) n := float64(0) + packetsReceived := uint64(0) + packetsSent := uint64(0) + packetsLost := uint64(0) if atomic.LoadInt64(co.startedReading) == 1 { for _, tr := range co.incomingTracks { if recvStats := tr.rtpReceiver.Stats(); recvStats != nil { v += recvStats.Jitter n++ + packetsReceived += recvStats.TotalReceived + packetsLost += recvStats.TotalLost } } } + for _, tr := range co.OutgoingTracks { + if sentStats := tr.rtcpSender.Stats(); sentStats != nil { + packetsSent += sentStats.TotalSent + } + } + var rtpPacketsJitter float64 if n != 0 { rtpPacketsJitter = v / n @@ -830,9 +833,9 @@ func (co *PeerConnection) Stats() *Stats { return &Stats{ BytesReceived: bytesReceived, BytesSent: bytesSent, - RTPPacketsReceived: atomic.LoadUint64(co.rtpPacketsReceived), - RTPPacketsSent: atomic.LoadUint64(co.rtpPacketsSent), - RTPPacketsLost: atomic.LoadUint64(co.rtpPacketsLost), + RTPPacketsReceived: packetsReceived, + RTPPacketsSent: packetsSent, + RTPPacketsLost: packetsLost, RTPPacketsJitter: rtpPacketsJitter, RTCPPacketsReceived: atomic.LoadUint64(co.statsInterceptor.rtcpPacketsReceived), RTCPPacketsSent: atomic.LoadUint64(co.statsInterceptor.rtcpPacketsSent),