@@ -10,6 +10,7 @@ import (
1010 "bufio"
1111 "bytes"
1212 "context"
13+ "crypto/rand"
1314 "errors"
1415 "fmt"
1516 "io"
@@ -2062,14 +2063,13 @@ func TestPeerConnection_Simulcast_RTX(t *testing.T) { //nolint:cyclop
20622063 assert .NotZero (t , ridID )
20632064 assert .NotZero (t , rsid )
20642065
2065- err = signalPairWithModification (pcOffer , pcAnswer , func (sdp string ) string {
2066+ assert . NoError ( t , signalPairWithModification (pcOffer , pcAnswer , func (sdp string ) string {
20662067 // Original chrome sdp contains no ssrc info https://pastebin.com/raw/JTjX6zg6
20672068 re := regexp .MustCompile ("(?m)[\r \n ]+^.*a=ssrc.*$" )
20682069 res := re .ReplaceAllString (sdp , "" )
20692070
20702071 return res
2071- })
2072- assert .NoError (t , err )
2072+ }))
20732073
20742074 // padding only packets should not affect simulcast probe
20752075 var sequenceNumber uint16
@@ -2493,3 +2493,105 @@ func Test_PeerConnection_RTX_E2E(t *testing.T) { //nolint:cyclop
24932493 closePairNow (t , pcOffer , pcAnswer )
24942494 assert .NoError (t , wan .Stop ())
24952495}
2496+
2497+ // Simulcast probe would lose packets. This test asserts that we don't drop
2498+ // any packets during the probe.
2499+ func TestPeerConnection_Simulcast_Probe_PacketLoss (t * testing.T ) { //nolint:cyclop
2500+ lim := test .TimeOut (time .Second * 30 )
2501+ defer lim .Stop ()
2502+
2503+ report := test .CheckRoutines (t )
2504+ defer report ()
2505+
2506+ const rtpPktCount = 10
2507+ pcOffer , pcAnswer , wan := createVNetPair (t , nil )
2508+
2509+ rids := []string {"a" , "b" , "c" }
2510+ vp8WriterA , err := NewTrackLocalStaticRTP (
2511+ RTPCodecCapability {MimeType : MimeTypeVP8 }, "video" , "pion2" , WithRTPStreamID (rids [0 ]),
2512+ )
2513+ assert .NoError (t , err )
2514+
2515+ vp8WriterB , err := NewTrackLocalStaticRTP (
2516+ RTPCodecCapability {MimeType : MimeTypeVP8 }, "video" , "pion2" , WithRTPStreamID (rids [1 ]),
2517+ )
2518+ assert .NoError (t , err )
2519+
2520+ vp8WriterC , err := NewTrackLocalStaticRTP (
2521+ RTPCodecCapability {MimeType : MimeTypeVP8 }, "video" , "pion2" , WithRTPStreamID (rids [2 ]),
2522+ )
2523+ assert .NoError (t , err )
2524+
2525+ sender , err := pcOffer .AddTrack (vp8WriterA )
2526+ assert .NoError (t , err )
2527+ assert .NotNil (t , sender )
2528+
2529+ assert .NoError (t , sender .AddEncoding (vp8WriterB ))
2530+ assert .NoError (t , sender .AddEncoding (vp8WriterC ))
2531+
2532+ expectedBuffer := make ([]byte , outboundMTU * rtpPktCount )
2533+ _ , err = rand .Read (expectedBuffer )
2534+ assert .NoError (t , err )
2535+
2536+ ctx , cancel := context .WithCancel (context .Background ())
2537+ pcAnswer .OnTrack (func (trackRemote * TrackRemote , _ * RTPReceiver ) {
2538+ actualBuffer := []byte {}
2539+
2540+ for i := 0 ; i < rtpPktCount ; i ++ {
2541+ pkt , _ , err := trackRemote .ReadRTP ()
2542+ assert .NoError (t , err )
2543+
2544+ actualBuffer = append (actualBuffer , pkt .Payload ... )
2545+ }
2546+
2547+ assert .Equal (t , actualBuffer , expectedBuffer )
2548+ cancel ()
2549+ })
2550+
2551+ var midID , ridID uint8
2552+ for _ , extension := range sender .GetParameters ().HeaderExtensions {
2553+ switch extension .URI {
2554+ case sdp .SDESMidURI :
2555+ midID = uint8 (extension .ID ) //nolint:gosec // G115
2556+ case sdp .SDESRTPStreamIDURI :
2557+ ridID = uint8 (extension .ID ) //nolint:gosec // G115
2558+ }
2559+ }
2560+ assert .NotZero (t , midID )
2561+ assert .NotZero (t , ridID )
2562+
2563+ assert .NoError (t , signalPairWithModification (pcOffer , pcAnswer , func (sdp string ) string {
2564+ // Original chrome sdp contains no ssrc info https://pastebin.com/raw/JTjX6zg6
2565+ re := regexp .MustCompile ("(?m)[\r \n ]+^.*a=ssrc.*$" )
2566+ res := re .ReplaceAllString (sdp , "" )
2567+
2568+ return res
2569+ }))
2570+
2571+ peerConnectionConnected := untilConnectionState (PeerConnectionStateConnected , pcOffer , pcAnswer )
2572+ peerConnectionConnected .Wait ()
2573+
2574+ for sequenceNumber := uint16 (0 ); sequenceNumber < rtpPktCount ; sequenceNumber ++ {
2575+ pkt := & rtp.Packet {
2576+ Header : rtp.Header {
2577+ Version : 2 ,
2578+ PayloadType : 96 ,
2579+ SequenceNumber : sequenceNumber ,
2580+ },
2581+ }
2582+
2583+ // Make sure that packets for Stream received before MID/RID don't get dropped
2584+ if sequenceNumber > 3 {
2585+ assert .NoError (t , pkt .SetExtension (midID , []byte ("0" )))
2586+ assert .NoError (t , pkt .SetExtension (ridID , []byte (vp8WriterA .RID ())))
2587+ }
2588+
2589+ offset := int (sequenceNumber ) * outboundMTU
2590+ pkt .Payload = expectedBuffer [offset : offset + outboundMTU ]
2591+ assert .NoError (t , vp8WriterA .WriteRTP (pkt ))
2592+ }
2593+
2594+ <- ctx .Done ()
2595+ assert .NoError (t , wan .Stop ())
2596+ closePairNow (t , pcOffer , pcAnswer )
2597+ }
0 commit comments