github.com/pion/webrtc/v3@v3.2.24/pkg/media/samplebuilder/samplebuilder_test.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package samplebuilder 5 6 import ( 7 "fmt" 8 "testing" 9 "time" 10 11 "github.com/pion/rtp" 12 "github.com/pion/webrtc/v3/pkg/media" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 type sampleBuilderTest struct { 17 message string 18 packets []*rtp.Packet 19 withHeadChecker bool 20 headBytes []byte 21 samples []*media.Sample 22 maxLate uint16 23 maxLateTimestamp uint32 24 } 25 26 type fakeDepacketizer struct { 27 headChecker bool 28 headBytes []byte 29 } 30 31 func (f *fakeDepacketizer) Unmarshal(r []byte) ([]byte, error) { 32 return r, nil 33 } 34 35 func (f *fakeDepacketizer) IsPartitionHead(payload []byte) bool { 36 if !f.headChecker { 37 // simulates a bug in the 3.0 version 38 // the tests should be fixed to not assume the bug 39 return true 40 } 41 for _, b := range f.headBytes { 42 if payload[0] == b { 43 return true 44 } 45 } 46 return false 47 } 48 49 func (f *fakeDepacketizer) IsPartitionTail(marker bool, _ []byte) bool { 50 return marker 51 } 52 53 func TestSampleBuilder(t *testing.T) { 54 testData := []sampleBuilderTest{ 55 { 56 message: "SampleBuilder shouldn't emit anything if only one RTP packet has been pushed", 57 packets: []*rtp.Packet{ 58 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 59 }, 60 samples: []*media.Sample{}, 61 maxLate: 50, 62 maxLateTimestamp: 0, 63 }, 64 { 65 message: "SampleBuilder shouldn't emit anything if only one RTP packet has been pushed even if the market bit is set", 66 packets: []*rtp.Packet{ 67 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5, Marker: true}, Payload: []byte{0x01}}, 68 }, 69 samples: []*media.Sample{}, 70 maxLate: 50, 71 maxLateTimestamp: 0, 72 }, 73 { 74 message: "SampleBuilder should emit two packets, we had three packets with unique timestamps", 75 packets: []*rtp.Packet{ 76 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 77 {Header: rtp.Header{SequenceNumber: 5001, Timestamp: 6}, Payload: []byte{0x02}}, 78 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 7}, Payload: []byte{0x03}}, 79 }, 80 samples: []*media.Sample{ 81 {Data: []byte{0x01}, Duration: time.Second, PacketTimestamp: 5}, 82 {Data: []byte{0x02}, Duration: time.Second, PacketTimestamp: 6}, 83 }, 84 maxLate: 50, 85 maxLateTimestamp: 0, 86 }, 87 { 88 message: "SampleBuilder should emit one packet, we had a packet end of sequence marker and run out of space", 89 packets: []*rtp.Packet{ 90 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5, Marker: true}, Payload: []byte{0x01}}, 91 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 7}, Payload: []byte{0x02}}, 92 {Header: rtp.Header{SequenceNumber: 5004, Timestamp: 9}, Payload: []byte{0x03}}, 93 {Header: rtp.Header{SequenceNumber: 5006, Timestamp: 11}, Payload: []byte{0x04}}, 94 {Header: rtp.Header{SequenceNumber: 5008, Timestamp: 13}, Payload: []byte{0x05}}, 95 {Header: rtp.Header{SequenceNumber: 5010, Timestamp: 15}, Payload: []byte{0x06}}, 96 {Header: rtp.Header{SequenceNumber: 5012, Timestamp: 17}, Payload: []byte{0x07}}, 97 }, 98 samples: []*media.Sample{ 99 {Data: []byte{0x01}, Duration: time.Second * 2, PacketTimestamp: 5}, 100 }, 101 maxLate: 5, 102 maxLateTimestamp: 0, 103 }, 104 { 105 message: "SampleBuilder shouldn't emit any packet, we do not have a valid end of sequence and run out of space", 106 packets: []*rtp.Packet{ 107 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 108 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 7}, Payload: []byte{0x02}}, 109 {Header: rtp.Header{SequenceNumber: 5004, Timestamp: 9}, Payload: []byte{0x03}}, 110 {Header: rtp.Header{SequenceNumber: 5006, Timestamp: 11}, Payload: []byte{0x04}}, 111 {Header: rtp.Header{SequenceNumber: 5008, Timestamp: 13}, Payload: []byte{0x05}}, 112 {Header: rtp.Header{SequenceNumber: 5010, Timestamp: 15}, Payload: []byte{0x06}}, 113 {Header: rtp.Header{SequenceNumber: 5012, Timestamp: 17}, Payload: []byte{0x07}}, 114 }, 115 samples: []*media.Sample{}, 116 maxLate: 5, 117 maxLateTimestamp: 0, 118 }, 119 { 120 message: "SampleBuilder should emit one packet, we had a packet end of sequence marker and run out of space", 121 packets: []*rtp.Packet{ 122 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5, Marker: true}, Payload: []byte{0x01}}, 123 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 7, Marker: true}, Payload: []byte{0x02}}, 124 {Header: rtp.Header{SequenceNumber: 5004, Timestamp: 9}, Payload: []byte{0x03}}, 125 {Header: rtp.Header{SequenceNumber: 5006, Timestamp: 11}, Payload: []byte{0x04}}, 126 {Header: rtp.Header{SequenceNumber: 5008, Timestamp: 13}, Payload: []byte{0x05}}, 127 {Header: rtp.Header{SequenceNumber: 5010, Timestamp: 15}, Payload: []byte{0x06}}, 128 {Header: rtp.Header{SequenceNumber: 5012, Timestamp: 17}, Payload: []byte{0x07}}, 129 }, 130 samples: []*media.Sample{ 131 {Data: []byte{0x01}, Duration: time.Second * 2, PacketTimestamp: 5}, 132 {Data: []byte{0x02}, Duration: time.Second * 2, PacketTimestamp: 7, PrevDroppedPackets: 1}, 133 }, 134 maxLate: 5, 135 maxLateTimestamp: 0, 136 }, 137 { 138 message: "SampleBuilder should emit one packet, we had two packets but two with duplicate timestamps", 139 packets: []*rtp.Packet{ 140 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 141 {Header: rtp.Header{SequenceNumber: 5001, Timestamp: 6}, Payload: []byte{0x02}}, 142 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 6}, Payload: []byte{0x03}}, 143 {Header: rtp.Header{SequenceNumber: 5003, Timestamp: 7}, Payload: []byte{0x04}}, 144 }, 145 samples: []*media.Sample{ 146 {Data: []byte{0x01}, Duration: time.Second, PacketTimestamp: 5}, 147 {Data: []byte{0x02, 0x03}, Duration: time.Second, PacketTimestamp: 6}, 148 }, 149 maxLate: 50, 150 maxLateTimestamp: 0, 151 }, 152 { 153 message: "SampleBuilder shouldn't emit a packet because we have a gap before a valid one", 154 packets: []*rtp.Packet{ 155 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 156 {Header: rtp.Header{SequenceNumber: 5007, Timestamp: 6}, Payload: []byte{0x02}}, 157 {Header: rtp.Header{SequenceNumber: 5008, Timestamp: 7}, Payload: []byte{0x03}}, 158 }, 159 samples: []*media.Sample{}, 160 maxLate: 50, 161 maxLateTimestamp: 0, 162 }, 163 { 164 message: "SampleBuilder shouldn't emit a packet after a gap as there are gaps and have not reached maxLate yet", 165 packets: []*rtp.Packet{ 166 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 167 {Header: rtp.Header{SequenceNumber: 5007, Timestamp: 6}, Payload: []byte{0x02}}, 168 {Header: rtp.Header{SequenceNumber: 5008, Timestamp: 7}, Payload: []byte{0x03}}, 169 }, 170 withHeadChecker: true, 171 headBytes: []byte{0x02}, 172 samples: []*media.Sample{}, 173 maxLate: 50, 174 maxLateTimestamp: 0, 175 }, 176 { 177 message: "SampleBuilder shouldn't emit a packet after a gap if PartitionHeadChecker doesn't assume it head", 178 packets: []*rtp.Packet{ 179 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 180 {Header: rtp.Header{SequenceNumber: 5007, Timestamp: 6}, Payload: []byte{0x02}}, 181 {Header: rtp.Header{SequenceNumber: 5008, Timestamp: 7}, Payload: []byte{0x03}}, 182 }, 183 withHeadChecker: true, 184 headBytes: []byte{}, 185 samples: []*media.Sample{}, 186 maxLate: 50, 187 maxLateTimestamp: 0, 188 }, 189 { 190 message: "SampleBuilder should emit multiple valid packets", 191 packets: []*rtp.Packet{ 192 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 1}, Payload: []byte{0x01}}, 193 {Header: rtp.Header{SequenceNumber: 5001, Timestamp: 2}, Payload: []byte{0x02}}, 194 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 3}, Payload: []byte{0x03}}, 195 {Header: rtp.Header{SequenceNumber: 5003, Timestamp: 4}, Payload: []byte{0x04}}, 196 {Header: rtp.Header{SequenceNumber: 5004, Timestamp: 5}, Payload: []byte{0x05}}, 197 {Header: rtp.Header{SequenceNumber: 5005, Timestamp: 6}, Payload: []byte{0x06}}, 198 }, 199 samples: []*media.Sample{ 200 {Data: []byte{0x01}, Duration: time.Second, PacketTimestamp: 1}, 201 {Data: []byte{0x02}, Duration: time.Second, PacketTimestamp: 2}, 202 {Data: []byte{0x03}, Duration: time.Second, PacketTimestamp: 3}, 203 {Data: []byte{0x04}, Duration: time.Second, PacketTimestamp: 4}, 204 {Data: []byte{0x05}, Duration: time.Second, PacketTimestamp: 5}, 205 }, 206 maxLate: 50, 207 maxLateTimestamp: 0, 208 }, 209 { 210 message: "SampleBuilder should skip time stamps too old", 211 packets: []*rtp.Packet{ 212 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 1}, Payload: []byte{0x01}}, 213 {Header: rtp.Header{SequenceNumber: 5001, Timestamp: 2}, Payload: []byte{0x02}}, 214 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 3}, Payload: []byte{0x03}}, 215 {Header: rtp.Header{SequenceNumber: 5013, Timestamp: 4000}, Payload: []byte{0x04}}, 216 {Header: rtp.Header{SequenceNumber: 5014, Timestamp: 4000}, Payload: []byte{0x05}}, 217 {Header: rtp.Header{SequenceNumber: 5015, Timestamp: 4002}, Payload: []byte{0x06}}, 218 {Header: rtp.Header{SequenceNumber: 5016, Timestamp: 7000}, Payload: []byte{0x04}}, 219 {Header: rtp.Header{SequenceNumber: 5017, Timestamp: 7001}, Payload: []byte{0x05}}, 220 }, 221 samples: []*media.Sample{ 222 {Data: []byte{0x04, 0x05}, Duration: time.Second * time.Duration(2), PacketTimestamp: 4000, PrevDroppedPackets: 13}, 223 }, 224 withHeadChecker: true, 225 headBytes: []byte{0x04}, 226 maxLate: 50, 227 maxLateTimestamp: 2000, 228 }, 229 } 230 231 t.Run("Pop", func(t *testing.T) { 232 assert := assert.New(t) 233 234 for _, t := range testData { 235 var opts []Option 236 if t.maxLateTimestamp != 0 { 237 opts = append(opts, WithMaxTimeDelay( 238 time.Millisecond*time.Duration(int64(t.maxLateTimestamp)), 239 )) 240 } 241 242 d := &fakeDepacketizer{ 243 headChecker: t.withHeadChecker, 244 headBytes: t.headBytes, 245 } 246 s := New(t.maxLate, d, 1, opts...) 247 samples := []*media.Sample{} 248 249 for _, p := range t.packets { 250 s.Push(p) 251 } 252 for sample := s.Pop(); sample != nil; sample = s.Pop() { 253 samples = append(samples, sample) 254 } 255 assert.Equal(t.samples, samples, t.message) 256 } 257 }) 258 } 259 260 // SampleBuilder should respect maxLate if we popped successfully but then have a gap larger then maxLate 261 func TestSampleBuilderMaxLate(t *testing.T) { 262 assert := assert.New(t) 263 s := New(50, &fakeDepacketizer{}, 1) 264 265 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 0, Timestamp: 1}, Payload: []byte{0x01}}) 266 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 1, Timestamp: 2}, Payload: []byte{0x01}}) 267 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 2, Timestamp: 3}, Payload: []byte{0x01}}) 268 assert.Equal(&media.Sample{Data: []byte{0x01}, Duration: time.Second, PacketTimestamp: 1}, s.Pop(), "Failed to build samples before gap") 269 270 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 5000, Timestamp: 500}, Payload: []byte{0x02}}) 271 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 5001, Timestamp: 501}, Payload: []byte{0x02}}) 272 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 5002, Timestamp: 502}, Payload: []byte{0x02}}) 273 274 assert.Equal(&media.Sample{Data: []byte{0x01}, Duration: time.Second, PacketTimestamp: 2}, s.Pop(), "Failed to build samples after large gap") 275 assert.Equal((*media.Sample)(nil), s.Pop(), "Failed to build samples after large gap") 276 277 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 6000, Timestamp: 600}, Payload: []byte{0x03}}) 278 assert.Equal(&media.Sample{Data: []byte{0x02}, Duration: time.Second, PacketTimestamp: 500, PrevDroppedPackets: 4998}, s.Pop(), "Failed to build samples after large gap") 279 assert.Equal(&media.Sample{Data: []byte{0x02}, Duration: time.Second, PacketTimestamp: 501}, s.Pop(), "Failed to build samples after large gap") 280 } 281 282 func TestSeqnumDistance(t *testing.T) { 283 testData := []struct { 284 x uint16 285 y uint16 286 d uint16 287 }{ 288 {0x0001, 0x0003, 0x0002}, 289 {0x0003, 0x0001, 0x0002}, 290 {0xFFF3, 0xFFF1, 0x0002}, 291 {0xFFF1, 0xFFF3, 0x0002}, 292 {0xFFFF, 0x0001, 0x0002}, 293 {0x0001, 0xFFFF, 0x0002}, 294 } 295 296 for _, data := range testData { 297 if ret := seqnumDistance(data.x, data.y); ret != data.d { 298 t.Errorf("seqnumDistance(%d, %d) returned %d which must be %d", 299 data.x, data.y, ret, data.d) 300 } 301 } 302 } 303 304 func TestSampleBuilderCleanReference(t *testing.T) { 305 for _, seqStart := range []uint16{ 306 0, 307 0xFFF8, // check upper boundary 308 0xFFFE, // check upper boundary 309 } { 310 seqStart := seqStart 311 t.Run(fmt.Sprintf("From%d", seqStart), func(t *testing.T) { 312 s := New(10, &fakeDepacketizer{}, 1) 313 314 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 0 + seqStart, Timestamp: 0}, Payload: []byte{0x01}}) 315 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 1 + seqStart, Timestamp: 0}, Payload: []byte{0x02}}) 316 s.Push(&rtp.Packet{Header: rtp.Header{SequenceNumber: 2 + seqStart, Timestamp: 0}, Payload: []byte{0x03}}) 317 pkt4 := &rtp.Packet{Header: rtp.Header{SequenceNumber: 14 + seqStart, Timestamp: 120}, Payload: []byte{0x04}} 318 s.Push(pkt4) 319 pkt5 := &rtp.Packet{Header: rtp.Header{SequenceNumber: 12 + seqStart, Timestamp: 120}, Payload: []byte{0x05}} 320 s.Push(pkt5) 321 322 for i := 0; i < 3; i++ { 323 if s.buffer[(i+int(seqStart))%0x10000] != nil { 324 t.Errorf("Old packet (%d) is not unreferenced (maxLate: 10, pushed: 12)", i) 325 } 326 } 327 if s.buffer[(14+int(seqStart))%0x10000] != pkt4 { 328 t.Error("New packet must be referenced after jump") 329 } 330 if s.buffer[(12+int(seqStart))%0x10000] != pkt5 { 331 t.Error("New packet must be referenced after jump") 332 } 333 }) 334 } 335 } 336 337 func TestSampleBuilderPushMaxZero(t *testing.T) { 338 // Test packets released via 'maxLate' of zero. 339 pkts := []rtp.Packet{ 340 {Header: rtp.Header{SequenceNumber: 0, Timestamp: 0, Marker: true}, Payload: []byte{0x01}}, 341 } 342 d := &fakeDepacketizer{ 343 headChecker: true, 344 headBytes: []byte{0x01}, 345 } 346 347 s := New(0, d, 1) 348 s.Push(&pkts[0]) 349 if sample := s.Pop(); sample == nil { 350 t.Error("Should expect a popped sample") 351 } 352 } 353 354 func TestSampleBuilderWithPacketReleaseHandler(t *testing.T) { 355 var released []*rtp.Packet 356 fakePacketReleaseHandler := func(p *rtp.Packet) { 357 released = append(released, p) 358 } 359 360 // Test packets released via 'maxLate'. 361 pkts := []rtp.Packet{ 362 {Header: rtp.Header{SequenceNumber: 0, Timestamp: 0}, Payload: []byte{0x01}}, 363 {Header: rtp.Header{SequenceNumber: 11, Timestamp: 120}, Payload: []byte{0x02}}, 364 {Header: rtp.Header{SequenceNumber: 12, Timestamp: 121}, Payload: []byte{0x03}}, 365 {Header: rtp.Header{SequenceNumber: 13, Timestamp: 122}, Payload: []byte{0x04}}, 366 {Header: rtp.Header{SequenceNumber: 21, Timestamp: 200}, Payload: []byte{0x05}}, 367 } 368 s := New(10, &fakeDepacketizer{}, 1, WithPacketReleaseHandler(fakePacketReleaseHandler)) 369 s.Push(&pkts[0]) 370 s.Push(&pkts[1]) 371 if len(released) == 0 { 372 t.Errorf("Old packet is not released") 373 } 374 if len(released) > 0 && released[0].SequenceNumber != pkts[0].SequenceNumber { 375 t.Errorf("Unexpected packet released by maxLate") 376 } 377 // Test packets released after samples built. 378 s.Push(&pkts[2]) 379 s.Push(&pkts[3]) 380 s.Push(&pkts[4]) 381 if s.Pop() == nil { 382 t.Errorf("Should have some sample here.") 383 } 384 if len(released) < 3 { 385 t.Errorf("packet built with sample is not released") 386 } 387 if len(released) >= 2 && released[2].SequenceNumber != pkts[2].SequenceNumber { 388 t.Errorf("Unexpected packet released by samples built") 389 } 390 } 391 392 func TestSampleBuilderWithPacketHeadHandler(t *testing.T) { 393 packets := []*rtp.Packet{ 394 {Header: rtp.Header{SequenceNumber: 5000, Timestamp: 5}, Payload: []byte{0x01}}, 395 {Header: rtp.Header{SequenceNumber: 5001, Timestamp: 5}, Payload: []byte{0x02}}, 396 {Header: rtp.Header{SequenceNumber: 5002, Timestamp: 6}, Payload: []byte{0x01}}, 397 {Header: rtp.Header{SequenceNumber: 5003, Timestamp: 6}, Payload: []byte{0x02}}, 398 {Header: rtp.Header{SequenceNumber: 5004, Timestamp: 7}, Payload: []byte{0x01}}, 399 } 400 401 headCount := 0 402 s := New(10, &fakeDepacketizer{}, 1, WithPacketHeadHandler(func(headPacket interface{}) interface{} { 403 headCount++ 404 return true 405 })) 406 407 for _, pkt := range packets { 408 s.Push(pkt) 409 } 410 411 for { 412 sample := s.Pop() 413 if sample == nil { 414 break 415 } 416 417 assert.NotNil(t, sample.Metadata, "sample metadata shouldn't be nil") 418 assert.Equal(t, true, sample.Metadata, "sample metadata should've been set to true") 419 } 420 421 assert.Equal(t, 2, headCount, "two sample heads should have been inspected") 422 } 423 424 func TestPopWithTimestamp(t *testing.T) { 425 t.Run("Crash on nil", func(t *testing.T) { 426 s := New(0, &fakeDepacketizer{}, 1) 427 sample, timestamp := s.PopWithTimestamp() 428 assert.Nil(t, sample) 429 assert.Equal(t, uint32(0), timestamp) 430 }) 431 } 432 433 type truePartitionHeadChecker struct{} 434 435 func (f *truePartitionHeadChecker) IsPartitionHead([]byte) bool { 436 return true 437 } 438 439 func TestSampleBuilderData(t *testing.T) { 440 s := New(10, &fakeDepacketizer{}, 1, 441 WithPartitionHeadChecker(&truePartitionHeadChecker{}), 442 ) 443 j := 0 444 for i := 0; i < 0x20000; i++ { 445 p := rtp.Packet{ 446 Header: rtp.Header{ 447 SequenceNumber: uint16(i), 448 Timestamp: uint32(i + 42), 449 }, 450 Payload: []byte{byte(i)}, 451 } 452 s.Push(&p) 453 for { 454 sample, ts := s.PopWithTimestamp() 455 if sample == nil { 456 break 457 } 458 assert.Equal(t, ts, uint32(j+42), "timestamp") 459 assert.Equal(t, len(sample.Data), 1, "data length") 460 assert.Equal(t, byte(j), sample.Data[0], "data") 461 j++ 462 } 463 } 464 // only the last packet should be dropped 465 assert.Equal(t, j, 0x1FFFF) 466 } 467 468 func BenchmarkSampleBuilderSequential(b *testing.B) { 469 s := New(100, &fakeDepacketizer{}, 1) 470 b.ResetTimer() 471 j := 0 472 for i := 0; i < b.N; i++ { 473 p := rtp.Packet{ 474 Header: rtp.Header{ 475 SequenceNumber: uint16(i), 476 Timestamp: uint32(i + 42), 477 }, 478 Payload: make([]byte, 50), 479 } 480 s.Push(&p) 481 for { 482 s := s.Pop() 483 if s == nil { 484 break 485 } 486 j++ 487 } 488 } 489 if b.N > 200 && j < b.N-100 { 490 b.Errorf("Got %v (N=%v)", j, b.N) 491 } 492 } 493 494 func BenchmarkSampleBuilderLoss(b *testing.B) { 495 s := New(100, &fakeDepacketizer{}, 1) 496 b.ResetTimer() 497 j := 0 498 for i := 0; i < b.N; i++ { 499 if i%13 == 0 { 500 continue 501 } 502 p := rtp.Packet{ 503 Header: rtp.Header{ 504 SequenceNumber: uint16(i), 505 Timestamp: uint32(i + 42), 506 }, 507 Payload: make([]byte, 50), 508 } 509 s.Push(&p) 510 for { 511 s := s.Pop() 512 if s == nil { 513 break 514 } 515 j++ 516 } 517 } 518 if b.N > 200 && j < b.N/2-100 { 519 b.Errorf("Got %v (N=%v)", j, b.N) 520 } 521 } 522 523 func BenchmarkSampleBuilderReordered(b *testing.B) { 524 s := New(100, &fakeDepacketizer{}, 1) 525 b.ResetTimer() 526 j := 0 527 for i := 0; i < b.N; i++ { 528 p := rtp.Packet{ 529 Header: rtp.Header{ 530 SequenceNumber: uint16(i ^ 3), 531 Timestamp: uint32((i ^ 3) + 42), 532 }, 533 Payload: make([]byte, 50), 534 } 535 s.Push(&p) 536 for { 537 s := s.Pop() 538 if s == nil { 539 break 540 } 541 j++ 542 } 543 } 544 if b.N > 2 && j < b.N-5 && j > b.N { 545 b.Errorf("Got %v (N=%v)", j, b.N) 546 } 547 } 548 549 func BenchmarkSampleBuilderFragmented(b *testing.B) { 550 s := New(100, &fakeDepacketizer{}, 1) 551 b.ResetTimer() 552 j := 0 553 for i := 0; i < b.N; i++ { 554 p := rtp.Packet{ 555 Header: rtp.Header{ 556 SequenceNumber: uint16(i), 557 Timestamp: uint32(i/2 + 42), 558 }, 559 Payload: make([]byte, 50), 560 } 561 s.Push(&p) 562 for { 563 s := s.Pop() 564 if s == nil { 565 break 566 } 567 j++ 568 } 569 } 570 if b.N > 200 && j < b.N/2-100 { 571 b.Errorf("Got %v (N=%v)", j, b.N) 572 } 573 } 574 575 func BenchmarkSampleBuilderFragmentedLoss(b *testing.B) { 576 s := New(100, &fakeDepacketizer{}, 1) 577 b.ResetTimer() 578 j := 0 579 for i := 0; i < b.N; i++ { 580 if i%13 == 0 { 581 continue 582 } 583 p := rtp.Packet{ 584 Header: rtp.Header{ 585 SequenceNumber: uint16(i), 586 Timestamp: uint32(i/2 + 42), 587 }, 588 Payload: make([]byte, 50), 589 } 590 s.Push(&p) 591 for { 592 s := s.Pop() 593 if s == nil { 594 break 595 } 596 j++ 597 } 598 } 599 if b.N > 200 && j < b.N/3-100 { 600 b.Errorf("Got %v (N=%v)", j, b.N) 601 } 602 }