@@ -435,3 +435,137 @@ func testInterceptorNack(t *testing.T, requestNack bool) {
435
435
}
436
436
}
437
437
}
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