| 60 | } |
| 61 | |
| 62 | func TestNack(t *testing.T) { |
| 63 | t.Run("nack normal", func(t *testing.T) { |
| 64 | buff := NewBuffer(123, 1, 1) |
| 65 | buff.codecType = webrtc.RTPCodecTypeVideo |
| 66 | require.NotNil(t, buff) |
| 67 | var wg sync.WaitGroup |
| 68 | // 5 tries |
| 69 | wg.Add(5) |
| 70 | buff.OnRtcpFeedback(func(fb []rtcp.Packet) { |
| 71 | for _, pkt := range fb { |
| 72 | switch p := pkt.(type) { |
| 73 | case *rtcp.TransportLayerNack: |
| 74 | if p.Nacks[0].PacketList()[0] == 1 && p.MediaSSRC == 123 { |
| 75 | wg.Done() |
| 76 | } |
| 77 | } |
| 78 | } |
| 79 | }) |
| 80 | buff.Bind(webrtc.RTPParameters{ |
| 81 | HeaderExtensions: nil, |
| 82 | Codecs: []webrtc.RTPCodecParameters{vp8Codec}, |
| 83 | }, vp8Codec.RTPCodecCapability, 0) |
| 84 | rtt := uint32(20) |
| 85 | buff.nacker.SetRTT(rtt) |
| 86 | for i := range 15 { |
| 87 | if i == 1 { |
| 88 | continue |
| 89 | } |
| 90 | if i < 14 { |
| 91 | time.Sleep(time.Duration(float64(rtt)*math.Pow(nack.NackQueueParamsDefault.BackoffFactor, float64(i))+10) * time.Millisecond) |
| 92 | } else { |
| 93 | time.Sleep(500 * time.Millisecond) // even a long wait should not exceed max retries |
| 94 | } |
| 95 | pkt := rtp.Packet{ |
| 96 | Header: rtp.Header{ |
| 97 | Version: 2, |
| 98 | PayloadType: 96, |
| 99 | SequenceNumber: uint16(i), |
| 100 | Timestamp: uint32(i), |
| 101 | SSRC: 123, |
| 102 | }, |
| 103 | Payload: []byte{0xff, 0xff, 0xff, 0xfd, 0xb4, 0x9f, 0x94, 0x1}, |
| 104 | } |
| 105 | b, err := pkt.Marshal() |
| 106 | require.NoError(t, err) |
| 107 | _, err = buff.Write(b) |
| 108 | require.NoError(t, err) |
| 109 | } |
| 110 | wg.Wait() |
| 111 | |
| 112 | }) |
| 113 | |
| 114 | t.Run("nack with seq wrap", func(t *testing.T) { |
| 115 | buff := NewBuffer(123, 1, 1) |
| 116 | buff.codecType = webrtc.RTPCodecTypeVideo |
| 117 | require.NotNil(t, buff) |
| 118 | var wg sync.WaitGroup |
| 119 | expects := map[uint16]int{ |