mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
144 lines
3.9 KiB
Go
144 lines
3.9 KiB
Go
package audio
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/pion/rtp"
|
|
)
|
|
|
|
func pkt(seq uint16) *rtp.Packet {
|
|
return &rtp.Packet{
|
|
Header: rtp.Header{SequenceNumber: seq, PayloadType: opusPayloadType},
|
|
Payload: []byte{0x00},
|
|
}
|
|
}
|
|
|
|
func TestPlayoutLateDrop(t *testing.T) {
|
|
p := NewPlayout(2)
|
|
p.Push(pkt(500))
|
|
p.Push(pkt(501))
|
|
// Drain to set the playout head past 500.
|
|
if _, _, err := p.PopOrSkip(); err != nil {
|
|
t.Fatalf("first pop: %v", err)
|
|
}
|
|
if _, _, err := p.PopOrSkip(); err != nil {
|
|
t.Fatalf("second pop: %v", err)
|
|
}
|
|
// A late packet with seq 499 must be dropped (not block, not surface
|
|
// later).
|
|
p.Push(pkt(499))
|
|
if _, _, err := p.PopOrSkip(); !errors.Is(err, ErrEmpty) {
|
|
t.Fatalf("late packet should not have been buffered; got err=%v", err)
|
|
}
|
|
}
|
|
|
|
func TestPlayoutSkipAhead(t *testing.T) {
|
|
p := NewPlayout(2)
|
|
// Push 600, 601 to prime, then drain so playoutHead = 602.
|
|
p.Push(pkt(600))
|
|
p.Push(pkt(601))
|
|
if _, _, err := p.PopOrSkip(); err != nil {
|
|
t.Fatalf("first pop: %v", err)
|
|
}
|
|
if _, _, err := p.PopOrSkip(); err != nil {
|
|
t.Fatalf("second pop: %v", err)
|
|
}
|
|
// Now skip seq 602, 603; deliver 604, 605.
|
|
p.Push(pkt(604))
|
|
p.Push(pkt(605))
|
|
got, gap, err := p.PopOrSkip()
|
|
if err != nil {
|
|
t.Fatalf("skip-ahead pop: %v", err)
|
|
}
|
|
if got.SequenceNumber != 604 {
|
|
t.Errorf("got seq=%d, want 604", got.SequenceNumber)
|
|
}
|
|
if gap != 2 {
|
|
t.Errorf("got gap=%d, want 2 (skipped 602, 603)", gap)
|
|
}
|
|
// Next pop should be 605 with no gap.
|
|
got, gap, err = p.PopOrSkip()
|
|
if err != nil {
|
|
t.Fatalf("follow-up pop: %v", err)
|
|
}
|
|
if got.SequenceNumber != 605 {
|
|
t.Errorf("got seq=%d, want 605", got.SequenceNumber)
|
|
}
|
|
if gap != 0 {
|
|
t.Errorf("follow-up gap=%d, want 0", gap)
|
|
}
|
|
}
|
|
|
|
func TestPlayoutHardCapTrim(t *testing.T) {
|
|
p := NewPlayout(2)
|
|
p.MaxDepth = 10
|
|
p.TargetDepth = 3
|
|
// Push one past the ceiling; the crossing push trims the oldest back to
|
|
// TargetDepth in one shot.
|
|
for seq := uint16(0); seq <= uint16(p.MaxDepth); seq++ { // seqs 0..10
|
|
p.Push(pkt(seq))
|
|
}
|
|
if got := p.Depth(); got != p.TargetDepth {
|
|
t.Fatalf("after overflow: depth=%d, want %d", got, p.TargetDepth)
|
|
}
|
|
// The three survivors are the newest packets (8, 9, 10); the next pop
|
|
// returns 8, proving the oldest were the ones dropped.
|
|
got, _, err := p.PopOrSkip()
|
|
if err != nil {
|
|
t.Fatalf("pop after trim: %v", err)
|
|
}
|
|
if got.SequenceNumber != 8 {
|
|
t.Errorf("oldest survivor seq=%d, want 8", got.SequenceNumber)
|
|
}
|
|
}
|
|
|
|
func TestPlayoutShedOne(t *testing.T) {
|
|
p := NewPlayout(2)
|
|
p.TargetDepth = 2
|
|
for seq := uint16(0); seq < 5; seq++ {
|
|
p.Push(pkt(seq))
|
|
}
|
|
// Depth 5, target 2: ShedOne drops the oldest and reports true until depth
|
|
// reaches the target, then leaves the buffer alone.
|
|
if !p.ShedOne(p.TargetDepth) || p.Depth() != 4 {
|
|
t.Fatalf("first shed: dropped=%v depth=%d, want true/4", true, p.Depth())
|
|
}
|
|
if !p.ShedOne(p.TargetDepth) || p.Depth() != 3 {
|
|
t.Fatalf("second shed: depth=%d, want 3", p.Depth())
|
|
}
|
|
p.ShedOne(p.TargetDepth) // depth 3 -> 2
|
|
if shed := p.ShedOne(p.TargetDepth); shed || p.Depth() != 2 {
|
|
t.Errorf("at target: shed=%v depth=%d, want false/2", shed, p.Depth())
|
|
}
|
|
// Shedding drops from the front: the oldest remaining is seq 3.
|
|
got, _, err := p.PopOrSkip()
|
|
if err != nil {
|
|
t.Fatalf("pop after shed: %v", err)
|
|
}
|
|
if got.SequenceNumber != 3 {
|
|
t.Errorf("oldest survivor seq=%d, want 3", got.SequenceNumber)
|
|
}
|
|
}
|
|
|
|
func TestPlayoutSeqWraparound(t *testing.T) {
|
|
p := NewPlayout(2)
|
|
// Push packets straddling the uint16 boundary: 65534, 65535, 0, 1.
|
|
for _, s := range []uint16{65534, 65535, 0, 1} {
|
|
p.Push(pkt(s))
|
|
}
|
|
// Should pop in correct order despite the wrap.
|
|
wantOrder := []uint16{65534, 65535, 0, 1}
|
|
for _, want := range wantOrder {
|
|
got, gap, err := p.PopOrSkip()
|
|
if err != nil {
|
|
t.Fatalf("Pop want=%d: %v", want, err)
|
|
}
|
|
if got.SequenceNumber != want {
|
|
t.Errorf("got seq=%d, want %d", got.SequenceNumber, want)
|
|
}
|
|
if gap != 0 {
|
|
t.Errorf("seq=%d gap=%d, want 0", want, gap)
|
|
}
|
|
}
|
|
}
|