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  }