mirror of
https://github.com/livekit/livekit.git
synced 2026-10-07 12:01:00 +00:00
refactor packet generation for tests into util
This commit is contained in:
@@ -18,7 +18,6 @@ import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -29,6 +28,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/sfu/testutils/rtptest"
|
||||
"github.com/livekit/mediatransportutil/pkg/twcc"
|
||||
)
|
||||
|
||||
@@ -47,34 +47,6 @@ var flexFECCodec = webrtc.RTPCodecParameters{
|
||||
PayloadType: webrtc.PayloadType(fecTestFECPT),
|
||||
}
|
||||
|
||||
func fecTestMediaPackets(t *testing.T, baseSN uint16, count int) []rtp.Packet {
|
||||
t.Helper()
|
||||
rng := rand.New(rand.NewSource(int64(baseSN)))
|
||||
pkts := make([]rtp.Packet, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
payload := make([]byte, 50+rng.Intn(200))
|
||||
rng.Read(payload)
|
||||
// valid VP8 payload descriptor (S=1, no extensions) so the video
|
||||
// packet processing in the buffer accepts the packet
|
||||
payload[0] = 0x10
|
||||
sn := baseSN + uint16(i)
|
||||
pkts = append(pkts, rtp.Packet{
|
||||
Header: rtp.Header{
|
||||
Version: 2,
|
||||
PayloadType: uint8(vp8Codec.PayloadType),
|
||||
SequenceNumber: sn,
|
||||
// derive timestamp from the sequence number so windows
|
||||
// generated separately stay monotonic
|
||||
Timestamp: 90000 + 3000*uint32(sn),
|
||||
SSRC: fecTestMediaSSRC,
|
||||
Marker: i == count-1,
|
||||
},
|
||||
Payload: payload,
|
||||
})
|
||||
}
|
||||
return pkts
|
||||
}
|
||||
|
||||
func bindFECTestBuffer(t *testing.T, buff *Buffer) {
|
||||
t.Helper()
|
||||
buff.codecType = webrtc.RTPCodecTypeVideo
|
||||
@@ -193,7 +165,7 @@ func TestBufferFECRecoversDroppedPacket(t *testing.T) {
|
||||
receivedDelta += received
|
||||
})
|
||||
|
||||
media := fecTestMediaPackets(t, 100, 10)
|
||||
media := rtptest.GenerateVP8Packets(100, 10, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
encoder := pionflexfec.NewFlexEncoder03(fecTestFECPT, fecTestFECSSRC)
|
||||
fecPackets := encoder.EncodeFec(media, 2)
|
||||
require.NotEmpty(t, fecPackets)
|
||||
@@ -246,7 +218,7 @@ func TestBufferFECRecoversEncryptedPayload(t *testing.T) {
|
||||
aead, err := cipher.NewGCM(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
media := fecTestMediaPackets(t, 120, 5)
|
||||
media := rtptest.GenerateVP8Packets(120, 5, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
plaintexts := make([][]byte, len(media))
|
||||
for i := range media {
|
||||
plaintexts[i] = append([]byte("encrypted-video-frame-"), byte(i))
|
||||
@@ -302,7 +274,7 @@ func TestBufferFECRecoveryCallbackCanReenterBuffer(t *testing.T) {
|
||||
callbackDone <- struct{}{}
|
||||
})
|
||||
|
||||
media := fecTestMediaPackets(t, 150, 5)
|
||||
media := rtptest.GenerateVP8Packets(150, 5, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
for i := range media {
|
||||
writePacket(t, primary, &media[i])
|
||||
}
|
||||
@@ -341,7 +313,7 @@ func TestBufferFECPairAfterPackets(t *testing.T) {
|
||||
bindFECTestBuffer(t, primary)
|
||||
|
||||
encoder := pionflexfec.NewFlexEncoder03(fecTestFECPT, fecTestFECSSRC)
|
||||
media := fecTestMediaPackets(t, 200, 10)
|
||||
media := rtptest.GenerateVP8Packets(200, 10, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
fecPackets := encoder.EncodeFec(media, 2)
|
||||
require.NotEmpty(t, fecPackets)
|
||||
|
||||
@@ -370,7 +342,7 @@ func TestBufferFECPairAfterPackets(t *testing.T) {
|
||||
assert.EqualValues(t, 1, stats.PacketsRecovered)
|
||||
|
||||
// the next window recovers normally
|
||||
media2 := fecTestMediaPackets(t, 210, 10)
|
||||
media2 := rtptest.GenerateVP8Packets(210, 10, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
fecPackets2 := encoder.EncodeFec(media2, 2)
|
||||
require.NotEmpty(t, fecPackets2)
|
||||
|
||||
@@ -402,7 +374,7 @@ func TestBufferFECCoupledBeforeBuffersExist(t *testing.T) {
|
||||
fecBuff := factory.GetOrNew(packetio.RTPBufferPacket, fecTestFECSSRC).(*Buffer)
|
||||
bindFECTestBuffer(t, primary)
|
||||
|
||||
media := fecTestMediaPackets(t, 300, 5)
|
||||
media := rtptest.GenerateVP8Packets(300, 5, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
encoder := pionflexfec.NewFlexEncoder03(fecTestFECPT, fecTestFECSSRC)
|
||||
fecPackets := encoder.EncodeFec(media, 1)
|
||||
require.NotEmpty(t, fecPackets)
|
||||
@@ -433,7 +405,7 @@ func TestBufferFECSequenceNumberWrap(t *testing.T) {
|
||||
fecBuff := factory.GetOrNew(packetio.RTPBufferPacket, fecTestFECSSRC).(*Buffer)
|
||||
bindFECTestBuffer(t, primary)
|
||||
|
||||
media := fecTestMediaPackets(t, 65533, 5)
|
||||
media := rtptest.GenerateVP8Packets(65533, 5, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
for i := range media {
|
||||
media[i].Timestamp = 90000 + 3000*uint32(i)
|
||||
}
|
||||
@@ -463,7 +435,7 @@ func TestBufferFECRecoveryAfterPaddingRemoval(t *testing.T) {
|
||||
fecBuff := factory.GetOrNew(packetio.RTPBufferPacket, fecTestFECSSRC).(*Buffer)
|
||||
bindFECTestBuffer(t, primary)
|
||||
|
||||
media := fecTestMediaPackets(t, 800, 5)
|
||||
media := rtptest.GenerateVP8Packets(800, 5, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
fecPackets := pionflexfec.NewFlexEncoder03(fecTestFECPT, fecTestFECSSRC).EncodeFec(media, 1)
|
||||
require.Len(t, fecPackets, 1)
|
||||
|
||||
@@ -532,7 +504,7 @@ func TestBufferFECIgnoresUnexpectedPayloadType(t *testing.T) {
|
||||
Codecs: []webrtc.RTPCodecParameters{vp8Codec},
|
||||
}, vp8Codec.RTPCodecCapability, 0))
|
||||
|
||||
media := fecTestMediaPackets(t, 400, 5)
|
||||
media := rtptest.GenerateVP8Packets(400, 5, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
encoder := pionflexfec.NewFlexEncoder03(fecTestFECPT, fecTestFECSSRC)
|
||||
fecPackets := encoder.EncodeFec(media, 1)
|
||||
require.NotEmpty(t, fecPackets)
|
||||
@@ -585,7 +557,7 @@ func TestBufferFECNACKSuppression(t *testing.T) {
|
||||
factory.SetFECPair(fecTestFECSSRC, fecTestMediaSSRC)
|
||||
bindFECTestBuffer(t, primary)
|
||||
|
||||
media := fecTestMediaPackets(t, 700, 10)
|
||||
media := rtptest.GenerateVP8Packets(700, 10, uint8(vp8Codec.PayloadType), fecTestMediaSSRC)
|
||||
encoder := pionflexfec.NewFlexEncoder03(fecTestFECPT, fecTestFECSSRC)
|
||||
fecPackets := encoder.EncodeFec(media, 2)
|
||||
require.NotEmpty(t, fecPackets)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2026 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rtptest
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
// GenerateVP8Packets returns deterministic RTP packets with valid VP8 payload descriptors.
|
||||
func GenerateVP8Packets(baseSN uint16, count int, payloadType uint8, ssrc uint32) []rtp.Packet {
|
||||
rng := rand.New(rand.NewSource(int64(baseSN)))
|
||||
packets := make([]rtp.Packet, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
payload := make([]byte, 50+rng.Intn(200))
|
||||
rng.Read(payload)
|
||||
payload[0] = 0x10
|
||||
|
||||
sequenceNumber := baseSN + uint16(i)
|
||||
packets = append(packets, rtp.Packet{
|
||||
Header: rtp.Header{
|
||||
Version: 2,
|
||||
PayloadType: payloadType,
|
||||
SequenceNumber: sequenceNumber,
|
||||
Timestamp: 90000 + 3000*uint32(sequenceNumber),
|
||||
SSRC: ssrc,
|
||||
Marker: i == count-1,
|
||||
},
|
||||
Payload: payload,
|
||||
})
|
||||
}
|
||||
return packets
|
||||
}
|
||||
Reference in New Issue
Block a user