Skip to content

Commit fc9d59e

Browse files
committed
Implement TestInterceptorNackReply
This is another end-to-end test for the NACK interceptor, it verifies that we actually get a reply to a NACK, both with and without a negotiated RTX track.
1 parent 8f77dc4 commit fc9d59e

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

interceptor_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,3 +435,137 @@ func testInterceptorNack(t *testing.T, requestNack bool) {
435435
}
436436
}
437437
}
438+
439+
// TestInterceptorNackReply is an end-to-end test for the NACK responder.
440+
// It tests that we do receive a resent packet to a NACK, both with and
441+
// without negotiating an RTX track.
442+
func TestInterceptorNackReply(t *testing.T) {
443+
to := test.TimeOut(time.Second * 20)
444+
defer to.Stop()
445+
446+
t.Run("RTX", func(t *testing.T) { testInterceptorNackReply(t, true) })
447+
t.Run("NoRTX", func(t *testing.T) { testInterceptorNackReply(t, false) })
448+
}
449+
450+
func testInterceptorNackReply(t *testing.T, negotiateRTX bool) {
451+
ir := interceptor.Registry{}
452+
m := MediaEngine{}
453+
feedback := []RTCPFeedback{{"nack", ""}}
454+
err := m.RegisterCodec(
455+
RTPCodecParameters{
456+
RTPCodecCapability: RTPCodecCapability{
457+
"video/VP8", 90000, 0,
458+
"",
459+
feedback,
460+
},
461+
PayloadType: 96,
462+
},
463+
RTPCodecTypeVideo,
464+
)
465+
assert.NoError(t, err)
466+
467+
if negotiateRTX {
468+
err = m.RegisterCodec(
469+
RTPCodecParameters{
470+
RTPCodecCapability: RTPCodecCapability{
471+
MimeTypeRTX, 90000, 0,
472+
"apt=96",
473+
feedback,
474+
},
475+
PayloadType: 97,
476+
},
477+
RTPCodecTypeVideo,
478+
)
479+
}
480+
api := NewAPI(
481+
WithMediaEngine(&m),
482+
WithInterceptorRegistry(&ir),
483+
)
484+
485+
pc1, err := NewPeerConnection(Configuration{})
486+
assert.NoError(t, err)
487+
488+
track1, err := NewTrackLocalStaticRTP(
489+
RTPCodecCapability{MimeType: MimeTypeVP8},
490+
"video", "pion",
491+
)
492+
assert.NoError(t, err)
493+
sender, err := pc1.AddTrack(track1)
494+
assert.NoError(t, err)
495+
496+
pc2, err := api.NewPeerConnection(Configuration{})
497+
assert.NoError(t, err)
498+
499+
offer, err := pc1.CreateOffer(nil)
500+
assert.NoError(t, err)
501+
err = pc1.SetLocalDescription(offer)
502+
assert.NoError(t, err)
503+
<-GatheringCompletePromise(pc1)
504+
505+
err = pc2.SetRemoteDescription(*pc1.LocalDescription())
506+
assert.NoError(t, err)
507+
answer, err := pc2.CreateAnswer(nil)
508+
assert.NoError(t, err)
509+
err = pc2.SetLocalDescription(answer)
510+
assert.NoError(t, err)
511+
<-GatheringCompletePromise(pc2)
512+
513+
err = pc1.SetRemoteDescription(*pc2.LocalDescription())
514+
assert.NoError(t, err)
515+
516+
done := make(chan struct{})
517+
pc2.OnTrack(func(track2 *TrackRemote, _ *RTPReceiver) {
518+
defer close(done)
519+
p, _, err2 := track2.ReadRTP()
520+
assert.NoError(t, err2)
521+
time.Sleep(20 * time.Millisecond)
522+
err2 = pc2.WriteRTCP([]rtcp.Packet{
523+
&rtcp.TransportLayerNack{
524+
MediaSSRC: uint32(track2.SSRC()),
525+
Nacks: rtcp.NackPairsFromSequenceNumbers(
526+
[]uint16{p.SequenceNumber},
527+
),
528+
},
529+
})
530+
assert.NoError(t, err2)
531+
p2, _, err2 := track2.ReadRTP()
532+
assert.NoError(t, err2)
533+
assert.Equal(t, p.SequenceNumber, p2.SequenceNumber)
534+
assert.Equal(t, p.Timestamp, p2.Timestamp)
535+
assert.Equal(t, p.Payload, p2.Payload)
536+
})
537+
538+
rtcpDone := make(chan struct{})
539+
go func() {
540+
defer close(rtcpDone)
541+
buf := make([]byte, 1500)
542+
for {
543+
_, _, err2 := sender.Read(buf)
544+
// nolint
545+
if err2 == io.EOF {
546+
break
547+
}
548+
assert.NoError(t, err2)
549+
}
550+
}()
551+
552+
go func() {
553+
time.Sleep(20 * time.Millisecond)
554+
var p rtp.Packet
555+
p.Version = 2
556+
p.Marker = true
557+
p.PayloadType = 96
558+
p.SequenceNumber = 0
559+
p.Timestamp = 0
560+
p.Payload = []byte{42}
561+
err2 := track1.WriteRTP(&p)
562+
assert.NoError(t, err2)
563+
}()
564+
565+
<-done
566+
err = pc1.Close()
567+
assert.NoError(t, err)
568+
err = pc2.Close()
569+
assert.NoError(t, err)
570+
<-rtcpDone
571+
}

0 commit comments

Comments
 (0)