@@ -435,3 +435,138 @@ 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
+ assert .NoError (t , err )
480
+ }
481
+ api := NewAPI (
482
+ WithMediaEngine (& m ),
483
+ WithInterceptorRegistry (& ir ),
484
+ )
485
+
486
+ pc1 , err := NewPeerConnection (Configuration {})
487
+ assert .NoError (t , err )
488
+
489
+ track1 , err := NewTrackLocalStaticRTP (
490
+ RTPCodecCapability {MimeType : MimeTypeVP8 },
491
+ "video" , "pion" ,
492
+ )
493
+ assert .NoError (t , err )
494
+ sender , err := pc1 .AddTrack (track1 )
495
+ assert .NoError (t , err )
496
+
497
+ pc2 , err := api .NewPeerConnection (Configuration {})
498
+ assert .NoError (t , err )
499
+
500
+ offer , err := pc1 .CreateOffer (nil )
501
+ assert .NoError (t , err )
502
+ err = pc1 .SetLocalDescription (offer )
503
+ assert .NoError (t , err )
504
+ <- GatheringCompletePromise (pc1 )
505
+
506
+ err = pc2 .SetRemoteDescription (* pc1 .LocalDescription ())
507
+ assert .NoError (t , err )
508
+ answer , err := pc2 .CreateAnswer (nil )
509
+ assert .NoError (t , err )
510
+ err = pc2 .SetLocalDescription (answer )
511
+ assert .NoError (t , err )
512
+ <- GatheringCompletePromise (pc2 )
513
+
514
+ err = pc1 .SetRemoteDescription (* pc2 .LocalDescription ())
515
+ assert .NoError (t , err )
516
+
517
+ done := make (chan struct {})
518
+ pc2 .OnTrack (func (track2 * TrackRemote , _ * RTPReceiver ) {
519
+ defer close (done )
520
+ p , _ , err2 := track2 .ReadRTP ()
521
+ assert .NoError (t , err2 )
522
+ time .Sleep (20 * time .Millisecond )
523
+ err2 = pc2 .WriteRTCP ([]rtcp.Packet {
524
+ & rtcp.TransportLayerNack {
525
+ MediaSSRC : uint32 (track2 .SSRC ()),
526
+ Nacks : rtcp .NackPairsFromSequenceNumbers (
527
+ []uint16 {p .SequenceNumber },
528
+ ),
529
+ },
530
+ })
531
+ assert .NoError (t , err2 )
532
+ p2 , _ , err2 := track2 .ReadRTP ()
533
+ assert .NoError (t , err2 )
534
+ assert .Equal (t , p .SequenceNumber , p2 .SequenceNumber )
535
+ assert .Equal (t , p .Timestamp , p2 .Timestamp )
536
+ assert .Equal (t , p .Payload , p2 .Payload )
537
+ })
538
+
539
+ rtcpDone := make (chan struct {})
540
+ go func () {
541
+ defer close (rtcpDone )
542
+ buf := make ([]byte , 1500 )
543
+ for {
544
+ _ , _ , err2 := sender .Read (buf )
545
+ // nolint
546
+ if err2 == io .EOF {
547
+ break
548
+ }
549
+ assert .NoError (t , err2 )
550
+ }
551
+ }()
552
+
553
+ go func () {
554
+ time .Sleep (20 * time .Millisecond )
555
+ var p rtp.Packet
556
+ p .Version = 2
557
+ p .Marker = true
558
+ p .PayloadType = 96
559
+ p .SequenceNumber = 0
560
+ p .Timestamp = 0
561
+ p .Payload = []byte {42 }
562
+ err2 := track1 .WriteRTP (& p )
563
+ assert .NoError (t , err2 )
564
+ }()
565
+
566
+ <- done
567
+ err = pc1 .Close ()
568
+ assert .NoError (t , err )
569
+ err = pc2 .Close ()
570
+ assert .NoError (t , err )
571
+ <- rtcpDone
572
+ }
0 commit comments