Skip to content

Commit 3e555e2

Browse files
authored
fix crash when reading tracks with zero clock rate (bluenviron/mediamtx#4476) (#772)
also prevents RTCP sender and RTCP reports from being emitted when track has clock rate set to zero.
1 parent bfacd10 commit 3e555e2

File tree

6 files changed

+273
-55
lines changed

6 files changed

+273
-55
lines changed

client_media.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func (cm *clientMedia) stop() {
146146
}
147147
}
148148

149-
func (cm *clientMedia) findFormatWithSSRC(ssrc uint32) *clientFormat {
149+
func (cm *clientMedia) findFormatBySSRC(ssrc uint32) *clientFormat {
150150
for _, format := range cm.formats {
151151
stats := format.rtcpReceiver.Stats()
152152
if stats != nil && stats.RemoteSSRC == ssrc {
@@ -226,7 +226,7 @@ func (cm *clientMedia) readPacketRTCPTCPPlay(payload []byte) bool {
226226

227227
for _, pkt := range packets {
228228
if sr, ok := pkt.(*rtcp.SenderReport); ok {
229-
format := cm.findFormatWithSSRC(sr.SSRC)
229+
format := cm.findFormatBySSRC(sr.SSRC)
230230
if format != nil {
231231
format.rtcpReceiver.ProcessSenderReport(sr, now)
232232
}
@@ -311,7 +311,7 @@ func (cm *clientMedia) readPacketRTCPUDPPlay(payload []byte) bool {
311311

312312
for _, pkt := range packets {
313313
if sr, ok := pkt.(*rtcp.SenderReport); ok {
314-
format := cm.findFormatWithSSRC(sr.SSRC)
314+
format := cm.findFormatBySSRC(sr.SSRC)
315315
if format != nil {
316316
format.rtcpReceiver.ProcessSenderReport(sr, now)
317317
}

pkg/rtcpreceiver/rtcpreceiver.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ func (rr *RTCPReceiver) Initialize() error {
107107
return nil
108108
}
109109

110+
// Close closes the RTCPReceiver.
111+
func (rr *RTCPReceiver) Close() {
112+
close(rr.terminate)
113+
<-rr.done
114+
}
115+
110116
func (rr *RTCPReceiver) run() {
111117
defer close(rr.done)
112118

@@ -131,7 +137,7 @@ func (rr *RTCPReceiver) report() rtcp.Packet {
131137
rr.mutex.Lock()
132138
defer rr.mutex.Unlock()
133139

134-
if !rr.firstRTPPacketReceived {
140+
if !rr.firstRTPPacketReceived || rr.ClockRate == 0 {
135141
return nil
136142
}
137143

@@ -168,12 +174,6 @@ func (rr *RTCPReceiver) report() rtcp.Packet {
168174
return report
169175
}
170176

171-
// Close closes the RTCPReceiver.
172-
func (rr *RTCPReceiver) Close() {
173-
close(rr.terminate)
174-
<-rr.done
175-
}
176-
177177
// ProcessPacket extracts the needed data from RTP packets.
178178
func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, system time.Time, ptsEqualsDTS bool) error {
179179
rr.mutex.Lock()
@@ -223,7 +223,7 @@ func (rr *RTCPReceiver) ProcessPacket(pkt *rtp.Packet, system time.Time, ptsEqua
223223
rr.lastSequenceNumber = pkt.SequenceNumber
224224

225225
if ptsEqualsDTS {
226-
if rr.timeInitialized {
226+
if rr.timeInitialized && rr.ClockRate != 0 {
227227
// update jitter
228228
// https://tools.ietf.org/html/rfc3550#page-39
229229
D := system.Sub(rr.lastTimeSystem).Seconds()*float64(rr.ClockRate) -
@@ -255,7 +255,7 @@ func (rr *RTCPReceiver) ProcessSenderReport(sr *rtcp.SenderReport, system time.T
255255
}
256256

257257
func (rr *RTCPReceiver) packetNTPUnsafe(ts uint32) (time.Time, bool) {
258-
if !rr.firstSenderReportReceived {
258+
if !rr.firstSenderReportReceived || rr.ClockRate == 0 {
259259
return time.Time{}, false
260260
}
261261

pkg/rtcpreceiver/rtcpreceiver_test.go

Lines changed: 166 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ func uint32Ptr(v uint32) *uint32 {
1313
return &v
1414
}
1515

16-
func TestRTCPReceiverBase(t *testing.T) {
17-
done := make(chan struct{})
16+
func TestRTCPReceiver(t *testing.T) {
17+
pktGenerated := make(chan rtcp.Packet)
1818

1919
rr := &RTCPReceiver{
2020
ClockRate: 90000,
@@ -24,35 +24,173 @@ func TestRTCPReceiverBase(t *testing.T) {
2424
return time.Date(2008, 0o5, 20, 22, 15, 22, 0, time.UTC)
2525
},
2626
WritePacketRTCP: func(pkt rtcp.Packet) {
27-
require.Equal(t, &rtcp.ReceiverReport{
28-
SSRC: 0x65f83afb,
29-
Reports: []rtcp.ReceptionReport{
30-
{
31-
SSRC: 0xba9da416,
32-
LastSequenceNumber: 947,
33-
LastSenderReport: 0x887a17ce,
34-
Delay: 2 * 65536,
35-
},
36-
},
37-
}, pkt)
38-
close(done)
27+
pktGenerated <- pkt
28+
},
29+
}
30+
err := rr.Initialize()
31+
require.NoError(t, err)
32+
defer rr.Close()
33+
34+
stats := rr.Stats()
35+
require.Nil(t, stats)
36+
37+
rtpPkt := rtp.Packet{
38+
Header: rtp.Header{
39+
Version: 2,
40+
Marker: true,
41+
PayloadType: 96,
42+
SequenceNumber: 945,
43+
Timestamp: 0xafb45733,
44+
SSRC: 0xba9da416,
45+
},
46+
Payload: []byte("\x00\x00"),
47+
}
48+
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
49+
err = rr.ProcessPacket(&rtpPkt, ts, true)
50+
require.NoError(t, err)
51+
52+
stats = rr.Stats()
53+
require.Equal(t, &Stats{
54+
RemoteSSRC: 0xba9da416,
55+
LastRTP: 0xafb45733,
56+
LastSequenceNumber: 945,
57+
}, stats)
58+
59+
srPkt := rtcp.SenderReport{
60+
SSRC: 0xba9da416,
61+
NTPTime: func() uint64 {
62+
d := time.Date(2008, 5, 20, 22, 15, 20, 0, time.UTC)
63+
s := uint64(d.UnixNano()) + 2208988800*1000000000
64+
return (s/1000000000)<<32 | (s % 1000000000)
65+
}(),
66+
RTPTime: 0xafb45733,
67+
PacketCount: 714,
68+
OctetCount: 859127,
69+
}
70+
ts = time.Date(2008, 5, 20, 22, 15, 20, 0, time.UTC)
71+
rr.ProcessSenderReport(&srPkt, ts)
72+
73+
stats = rr.Stats()
74+
require.Equal(t, &Stats{
75+
RemoteSSRC: 0xba9da416,
76+
LastRTP: 0xafb45733,
77+
LastSequenceNumber: 945,
78+
LastNTP: time.Date(2008, 5, 20, 22, 15, 20, 0, time.UTC).Local(),
79+
}, stats)
80+
81+
rtpPkt = rtp.Packet{
82+
Header: rtp.Header{
83+
Version: 2,
84+
Marker: true,
85+
PayloadType: 96,
86+
SequenceNumber: 946,
87+
Timestamp: 0xafb45733,
88+
SSRC: 0xba9da416,
89+
},
90+
Payload: []byte("\x00\x00"),
91+
}
92+
ts = time.Date(2008, 5, 20, 22, 15, 20, 0, time.UTC)
93+
err = rr.ProcessPacket(&rtpPkt, ts, true)
94+
require.NoError(t, err)
95+
96+
rtpPkt = rtp.Packet{
97+
Header: rtp.Header{
98+
Version: 2,
99+
Marker: true,
100+
PayloadType: 96,
101+
SequenceNumber: 947,
102+
Timestamp: 0xafb45733 + 90000,
103+
SSRC: 0xba9da416,
104+
},
105+
Payload: []byte("\x00\x00"),
106+
}
107+
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
108+
err = rr.ProcessPacket(&rtpPkt, ts, true)
109+
require.NoError(t, err)
110+
111+
pkt := <-pktGenerated
112+
require.Equal(t, &rtcp.ReceiverReport{
113+
SSRC: 0x65f83afb,
114+
Reports: []rtcp.ReceptionReport{
115+
{
116+
SSRC: 0xba9da416,
117+
LastSequenceNumber: 947,
118+
LastSenderReport: 3422027776,
119+
Delay: 2 * 65536,
120+
},
121+
},
122+
}, pkt)
123+
124+
stats = rr.Stats()
125+
require.Equal(t, &Stats{
126+
RemoteSSRC: 0xba9da416,
127+
LastRTP: 2947921603,
128+
LastSequenceNumber: 947,
129+
LastNTP: time.Date(2008, 5, 20, 22, 15, 21, 0, time.UTC).Local(),
130+
}, stats)
131+
}
132+
133+
func TestRTCPReceiverZeroClockRate(t *testing.T) {
134+
pktGenerated := make(chan rtcp.Packet)
135+
136+
rr := &RTCPReceiver{
137+
ClockRate: 0,
138+
LocalSSRC: uint32Ptr(0x65f83afb),
139+
Period: 500 * time.Millisecond,
140+
TimeNow: func() time.Time {
141+
return time.Date(2008, 0o5, 20, 22, 15, 22, 0, time.UTC)
142+
},
143+
WritePacketRTCP: func(pkt rtcp.Packet) {
144+
pktGenerated <- pkt
39145
},
40146
}
41147
err := rr.Initialize()
42148
require.NoError(t, err)
43149
defer rr.Close()
44150

151+
stats := rr.Stats()
152+
require.Nil(t, stats)
153+
154+
rtpPkt := rtp.Packet{
155+
Header: rtp.Header{
156+
Version: 2,
157+
Marker: true,
158+
PayloadType: 96,
159+
SequenceNumber: 945,
160+
Timestamp: 0xafb45733,
161+
SSRC: 0xba9da416,
162+
},
163+
Payload: []byte("\x00\x00"),
164+
}
165+
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
166+
err = rr.ProcessPacket(&rtpPkt, ts, true)
167+
require.NoError(t, err)
168+
169+
stats = rr.Stats()
170+
require.Equal(t, &Stats{
171+
RemoteSSRC: 0xba9da416,
172+
LastRTP: 0xafb45733,
173+
LastSequenceNumber: 945,
174+
}, stats)
175+
45176
srPkt := rtcp.SenderReport{
46177
SSRC: 0xba9da416,
47178
NTPTime: 0xe363887a17ced916,
48179
RTPTime: 0xafb45733,
49180
PacketCount: 714,
50181
OctetCount: 859127,
51182
}
52-
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
183+
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
53184
rr.ProcessSenderReport(&srPkt, ts)
54185

55-
rtpPkt := rtp.Packet{
186+
stats = rr.Stats()
187+
require.Equal(t, &Stats{
188+
RemoteSSRC: 0xba9da416,
189+
LastRTP: 0xafb45733,
190+
LastSequenceNumber: 945,
191+
}, stats)
192+
193+
rtpPkt = rtp.Packet{
56194
Header: rtp.Header{
57195
Version: 2,
58196
Marker: true,
@@ -82,7 +220,18 @@ func TestRTCPReceiverBase(t *testing.T) {
82220
err = rr.ProcessPacket(&rtpPkt, ts, true)
83221
require.NoError(t, err)
84222

85-
<-done
223+
select {
224+
case <-pktGenerated:
225+
t.Error("should not happen")
226+
case <-time.After(500 * time.Millisecond):
227+
}
228+
229+
stats = rr.Stats()
230+
require.Equal(t, &Stats{
231+
RemoteSSRC: 0xba9da416,
232+
LastRTP: 2947921603,
233+
LastSequenceNumber: 947,
234+
}, stats)
86235
}
87236

88237
func TestRTCPReceiverOverflow(t *testing.T) {

pkg/rtcpsender/rtcpsender.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ func (rs *RTCPSender) Initialize() {
7171
go rs.run()
7272
}
7373

74+
// Close closes the RTCPSender.
75+
func (rs *RTCPSender) Close() {
76+
close(rs.terminate)
77+
<-rs.done
78+
}
79+
7480
func (rs *RTCPSender) run() {
7581
defer close(rs.done)
7682

@@ -95,7 +101,7 @@ func (rs *RTCPSender) report() rtcp.Packet {
95101
rs.mutex.Lock()
96102
defer rs.mutex.Unlock()
97103

98-
if !rs.firstRTPPacketSent {
104+
if !rs.firstRTPPacketSent || rs.ClockRate == 0 {
99105
return nil
100106
}
101107

@@ -112,12 +118,6 @@ func (rs *RTCPSender) report() rtcp.Packet {
112118
}
113119
}
114120

115-
// Close closes the RTCPSender.
116-
func (rs *RTCPSender) Close() {
117-
close(rs.terminate)
118-
<-rs.done
119-
}
120-
121121
// ProcessPacket extracts data from RTP packets.
122122
func (rs *RTCPSender) ProcessPacket(pkt *rtp.Packet, ntp time.Time, ptsEqualsDTS bool) {
123123
rs.mutex.Lock()

0 commit comments

Comments
 (0)