Skip to content

Commit d9a59a5

Browse files
committed
Add test for TrackRemote and RTX Packets
Relates to #2752
1 parent fc3ef75 commit d9a59a5

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

rtpreceiver_go_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,21 @@
77
package webrtc
88

99
import (
10+
"bufio"
1011
"context"
12+
"encoding/binary"
13+
"errors"
14+
"fmt"
15+
"io"
16+
"strconv"
17+
"strings"
1118
"testing"
1219
"time"
1320

21+
"github.com/pion/randutil"
22+
"github.com/pion/rtp"
1423
"github.com/pion/sdp/v3"
24+
"github.com/pion/transport/v3/test"
1525
"github.com/pion/webrtc/v4/pkg/media"
1626
"github.com/stretchr/testify/assert"
1727
)
@@ -70,3 +80,118 @@ func TestSetRTPParameters(t *testing.T) {
7080
assert.NoError(t, wan.Stop())
7181
closePairNow(t, sender, receiver)
7282
}
83+
84+
// Assert the behavior of reading a RTX with a distinct SSRC
85+
// All the attributes should be populated and the packet unpacked
86+
func Test_RTX_Read(t *testing.T) {
87+
defer test.TimeOut(time.Second * 30).Stop()
88+
89+
var ssrc *uint32
90+
ssrcLines := ""
91+
rtxSsrc := randutil.NewMathRandomGenerator().Uint32()
92+
93+
pcOffer, pcAnswer, err := newPair()
94+
assert.NoError(t, err)
95+
96+
track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "track-id", "stream-id")
97+
assert.NoError(t, err)
98+
99+
_, err = pcOffer.AddTrack(track)
100+
assert.NoError(t, err)
101+
102+
rtxRead, rtxReadCancel := context.WithCancel(context.Background())
103+
pcAnswer.OnTrack(func(track *TrackRemote, _ *RTPReceiver) {
104+
for {
105+
pkt, attributes, readRTPErr := track.ReadRTP()
106+
if errors.Is(readRTPErr, io.EOF) {
107+
return
108+
} else if pkt.PayloadType == 0 {
109+
continue
110+
}
111+
112+
assert.NoError(t, readRTPErr)
113+
assert.NotNil(t, pkt)
114+
assert.Equal(t, pkt.SSRC, *ssrc)
115+
assert.Equal(t, pkt.PayloadType, uint8(96))
116+
assert.Equal(t, pkt.Payload, []byte{0xB, 0xA, 0xD})
117+
118+
rtxPayloadType := attributes.Get(AttributeRtxPayloadType)
119+
rtxSequenceNumber := attributes.Get(AttributeRtxSequenceNumber)
120+
rtxSSRC := attributes.Get(AttributeRtxSsrc)
121+
if rtxPayloadType != nil && rtxSequenceNumber != nil && rtxSSRC != nil {
122+
assert.Equal(t, rtxPayloadType, uint8(97))
123+
assert.Equal(t, rtxSSRC, rtxSsrc)
124+
assert.Equal(t, rtxSequenceNumber, pkt.SequenceNumber+500)
125+
126+
rtxReadCancel()
127+
}
128+
}
129+
})
130+
131+
assert.NoError(t, signalPairWithModification(pcOffer, pcAnswer, func(offer string) (modified string) {
132+
scanner := bufio.NewScanner(strings.NewReader(offer))
133+
for scanner.Scan() {
134+
l := scanner.Text()
135+
136+
if strings.HasPrefix(l, "a=ssrc") {
137+
if ssrc == nil {
138+
lineSplit := strings.Split(l, " ")[0]
139+
parsed, atoiErr := strconv.ParseUint(strings.TrimPrefix(lineSplit, "a=ssrc:"), 10, 32)
140+
assert.NoError(t, atoiErr)
141+
142+
parsedSsrc := uint32(parsed)
143+
ssrc = &parsedSsrc
144+
145+
modified += fmt.Sprintf("a=ssrc-group:FID %d %d\r\n", *ssrc, rtxSsrc)
146+
}
147+
148+
ssrcLines += l + "\n"
149+
} else if ssrcLines != "" {
150+
ssrcLines = strings.ReplaceAll(ssrcLines, fmt.Sprintf("%d", *ssrc), fmt.Sprintf("%d", rtxSsrc))
151+
modified += ssrcLines
152+
ssrcLines = ""
153+
}
154+
155+
modified += l + "\n"
156+
}
157+
158+
return modified
159+
}))
160+
161+
func() {
162+
for i := uint16(0); ; i++ {
163+
pkt := rtp.Packet{
164+
Header: rtp.Header{
165+
Version: 2,
166+
SSRC: *ssrc,
167+
PayloadType: 96,
168+
SequenceNumber: i,
169+
},
170+
Payload: []byte{0xB, 0xA, 0xD},
171+
}
172+
173+
select {
174+
case <-time.After(20 * time.Millisecond):
175+
// Send the original packet
176+
err = track.WriteRTP(&pkt)
177+
assert.NoError(t, err)
178+
179+
rtxPayload := []byte{0x0, 0x0, 0xB, 0xA, 0xD}
180+
binary.BigEndian.PutUint16(rtxPayload[0:2], pkt.Header.SequenceNumber)
181+
182+
// Send the RTX
183+
_, err = track.bindings[0].writeStream.WriteRTP(&rtp.Header{
184+
Version: 2,
185+
SSRC: rtxSsrc,
186+
PayloadType: 97,
187+
SequenceNumber: i + 500,
188+
}, rtxPayload)
189+
assert.NoError(t, err)
190+
case <-rtxRead.Done():
191+
return
192+
}
193+
}
194+
}()
195+
196+
closePairNow(t, pcOffer, pcAnswer)
197+
}

0 commit comments

Comments
 (0)