@@ -92,6 +92,130 @@ func TestSenderInterceptor(t *testing.T) {
9292 }, sr )
9393 })
9494
95+ t .Run ("out of order RTP packets" , func (t * testing.T ) {
96+ mt := & test.MockTime {}
97+ f , err := NewSenderInterceptor (
98+ SenderInterval (time .Millisecond * 50 ),
99+ SenderLog (logging .NewDefaultLoggerFactory ().NewLogger ("test" )),
100+ SenderNow (mt .Now ),
101+ )
102+ assert .NoError (t , err )
103+
104+ i , err := f .NewInterceptor ("" )
105+ assert .NoError (t , err )
106+
107+ stream := test .NewMockStream (& interceptor.StreamInfo {
108+ SSRC : 123456 ,
109+ ClockRate : 90000 ,
110+ }, i )
111+ defer func () {
112+ assert .NoError (t , stream .Close ())
113+ }()
114+
115+ // Write several packets
116+ for i := 0 ; i < 10 ; i ++ {
117+ assert .NoError (t , stream .WriteRTP (& rtp.Packet {
118+ Header : rtp.Header {
119+ SequenceNumber : uint16 (i ),
120+ Timestamp : uint32 (i ),
121+ },
122+ Payload : []byte ("\x00 \x00 " ),
123+ }))
124+ }
125+
126+ // Skip a packet, then redeliver it out-of-order
127+ assert .NoError (t , stream .WriteRTP (& rtp.Packet {
128+ Header : rtp.Header {
129+ SequenceNumber : 12 ,
130+ Timestamp : 12 ,
131+ },
132+ Payload : []byte ("\x00 \x00 " ),
133+ }))
134+ assert .NoError (t , stream .WriteRTP (& rtp.Packet {
135+ Header : rtp.Header {
136+ SequenceNumber : 11 ,
137+ Timestamp : 11 ,
138+ },
139+ Payload : []byte ("\x00 \x00 " ),
140+ }))
141+
142+ pkts := <- stream .WrittenRTCP ()
143+ assert .Equal (t , len (pkts ), 1 )
144+ sr , ok := pkts [0 ].(* rtcp.SenderReport )
145+ assert .True (t , ok )
146+ // The out-of-order packet is included in PacketCount and OctetCount, but the RTP
147+ // timestamp of the last in-order packet is used for RTPTime
148+ assert .Equal (t , & rtcp.SenderReport {
149+ SSRC : 123456 ,
150+ NTPTime : ntp .ToNTP (mt .Now ()),
151+ RTPTime : 12 ,
152+ PacketCount : 12 ,
153+ OctetCount : 24 ,
154+ }, sr )
155+ })
156+
157+ t .Run ("out of order RTP packets with SenderUseLatestPacket" , func (t * testing.T ) {
158+ mt := & test.MockTime {}
159+ f , err := NewSenderInterceptor (
160+ SenderInterval (time .Millisecond * 50 ),
161+ SenderLog (logging .NewDefaultLoggerFactory ().NewLogger ("test" )),
162+ SenderNow (mt .Now ),
163+ SenderUseLatestPacket (),
164+ )
165+ assert .NoError (t , err )
166+
167+ i , err := f .NewInterceptor ("" )
168+ assert .NoError (t , err )
169+
170+ stream := test .NewMockStream (& interceptor.StreamInfo {
171+ SSRC : 123456 ,
172+ ClockRate : 90000 ,
173+ }, i )
174+ defer func () {
175+ assert .NoError (t , stream .Close ())
176+ }()
177+
178+ // Write several packets
179+ for i := 0 ; i < 10 ; i ++ {
180+ assert .NoError (t , stream .WriteRTP (& rtp.Packet {
181+ Header : rtp.Header {
182+ SequenceNumber : uint16 (i ),
183+ Timestamp : uint32 (i ),
184+ },
185+ Payload : []byte ("\x00 \x00 " ),
186+ }))
187+ }
188+
189+ // Skip a packet, then redeliver it out-of-order
190+ assert .NoError (t , stream .WriteRTP (& rtp.Packet {
191+ Header : rtp.Header {
192+ SequenceNumber : 12 ,
193+ Timestamp : 12 ,
194+ },
195+ Payload : []byte ("\x00 \x00 " ),
196+ }))
197+ assert .NoError (t , stream .WriteRTP (& rtp.Packet {
198+ Header : rtp.Header {
199+ SequenceNumber : 11 ,
200+ Timestamp : 11 ,
201+ },
202+ Payload : []byte ("\x00 \x00 " ),
203+ }))
204+
205+ pkts := <- stream .WrittenRTCP ()
206+ assert .Equal (t , len (pkts ), 1 )
207+ sr , ok := pkts [0 ].(* rtcp.SenderReport )
208+ assert .True (t , ok )
209+ // The out-of-order packet *is* used for RTPTime
210+ assert .Equal (t , & rtcp.SenderReport {
211+ SSRC : 123456 ,
212+ NTPTime : ntp .ToNTP (mt .Now ()),
213+ RTPTime : 11 ,
214+ PacketCount : 12 ,
215+ OctetCount : 24 ,
216+ }, sr )
217+ })
218+
95219 t .Run ("inject ticker" , func (t * testing.T ) {
96220 mNow := & test.MockTime {}
97221 mTick := & test.MockTicker {
0 commit comments