Skip to content

Commit bb41f23

Browse files
committed
Don't use JitterBuffer in SampleBuilder
The performance of the SampleBuilder is significantly worse when using the SampleBuilder. It would be good to evaluate improving the performance of the JitterBuffer. However for the time being we are just going to revert. Resolve pion#2778
1 parent dc1f8ff commit bb41f23

File tree

2 files changed

+23
-50
lines changed

2 files changed

+23
-50
lines changed

pkg/media/samplebuilder/samplebuilder.go

Lines changed: 20 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"math"
99
"time"
1010

11-
"github.com/pion/interceptor/pkg/jitterbuffer"
1211
"github.com/pion/rtp"
1312
"github.com/pion/webrtc/v4/pkg/media"
1413
)
@@ -17,7 +16,7 @@ import (
1716
type SampleBuilder struct {
1817
maxLate uint16 // how many packets to wait until we get a valid Sample
1918
maxLateTimestamp uint32 // max timestamp between old and new timestamps before dropping packets
20-
buffer *jitterbuffer.JitterBuffer
19+
buffer [math.MaxUint16 + 1]*rtp.Packet
2120
preparedSamples [math.MaxUint16 + 1]*media.Sample
2221

2322
// Interface that allows us to take RTP packets to samples
@@ -61,7 +60,7 @@ type SampleBuilder struct {
6160
// The depacketizer extracts media samples from RTP packets.
6261
// Several depacketizers are available in package github.com/pion/rtp/codecs.
6362
func New(maxLate uint16, depacketizer rtp.Depacketizer, sampleRate uint32, opts ...Option) *SampleBuilder {
64-
s := &SampleBuilder{maxLate: maxLate, depacketizer: depacketizer, sampleRate: sampleRate, buffer: jitterbuffer.New(jitterbuffer.WithMinimumPacketCount(1))}
63+
s := &SampleBuilder{maxLate: maxLate, depacketizer: depacketizer, sampleRate: sampleRate}
6564
for _, o := range opts {
6665
o(s)
6766
}
@@ -77,7 +76,7 @@ func (s *SampleBuilder) tooOld(location sampleSequenceLocation) bool {
7776
var foundTail *rtp.Packet
7877

7978
for i := location.head; i != location.tail; i++ {
80-
if packet, _ := s.buffer.PeekAtSequence(i); packet != nil {
79+
if packet := s.buffer[i]; packet != nil {
8180
foundHead = packet
8281
break
8382
}
@@ -88,7 +87,7 @@ func (s *SampleBuilder) tooOld(location sampleSequenceLocation) bool {
8887
}
8988

9089
for i := location.tail - 1; i != location.head; i-- {
91-
if packet, _ := s.buffer.PeekAtSequence(i); packet != nil {
90+
if packet := s.buffer[i]; packet != nil {
9291
foundTail = packet
9392
break
9493
}
@@ -106,16 +105,16 @@ func (s *SampleBuilder) fetchTimestamp(location sampleSequenceLocation) (timesta
106105
if location.empty() {
107106
return 0, false
108107
}
109-
packet, err := s.buffer.PeekAtSequence(location.head)
110-
if packet == nil || err != nil {
108+
packet := s.buffer[location.head]
109+
if packet == nil {
111110
return 0, false
112111
}
113112
return packet.Timestamp, true
114113
}
115114

116115
func (s *SampleBuilder) releasePacket(i uint16) {
117116
var p *rtp.Packet
118-
p, _ = s.buffer.PopAtSequence(i)
117+
p, s.buffer[i] = s.buffer[i], nil
119118
if p != nil && s.packetReleaseHandler != nil {
120119
s.packetReleaseHandler(p)
121120
}
@@ -179,7 +178,7 @@ func (s *SampleBuilder) purgeBuffers(flush bool) {
179178
// Push does not copy the input. If you wish to reuse
180179
// this memory make sure to copy before calling Push
181180
func (s *SampleBuilder) Push(p *rtp.Packet) {
182-
s.buffer.Push(p)
181+
s.buffer[p.SequenceNumber] = p
183182

184183
switch s.filled.compare(p.SequenceNumber) {
185184
case slCompareVoid:
@@ -221,19 +220,14 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
221220

222221
var consume sampleSequenceLocation
223222

224-
for i := s.active.head; s.active.compare(i) != slCompareAfter; i++ {
225-
pkt, err := s.buffer.PeekAtSequence(i)
226-
if pkt == nil || err != nil {
227-
break
228-
}
229-
230-
if s.depacketizer.IsPartitionTail(pkt.Marker, pkt.Payload) {
223+
for i := s.active.head; s.buffer[i] != nil && s.active.compare(i) != slCompareAfter; i++ {
224+
if s.depacketizer.IsPartitionTail(s.buffer[i].Marker, s.buffer[i].Payload) {
231225
consume.head = s.active.head
232226
consume.tail = i + 1
233227
break
234228
}
235229
headTimestamp, hasData := s.fetchTimestamp(s.active)
236-
if hasData && pkt.Timestamp != headTimestamp {
230+
if hasData && s.buffer[i].Timestamp != headTimestamp {
237231
consume.head = s.active.head
238232
consume.tail = i
239233
break
@@ -243,8 +237,8 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
243237
if consume.empty() {
244238
return nil
245239
}
246-
pkt, _ := s.buffer.PeekAtSequence(consume.tail)
247-
if !purgingBuffers && pkt == nil {
240+
241+
if !purgingBuffers && s.buffer[consume.tail] == nil {
248242
// wait for the next packet after this set of packets to arrive
249243
// to ensure at least one post sample timestamp is known
250244
// (unless we have to release right now)
@@ -256,10 +250,8 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
256250

257251
// scan for any packet after the current and use that time stamp as the diff point
258252
for i := consume.tail; i < s.active.tail; i++ {
259-
pkt, _ = s.buffer.PeekAtSequence(i)
260-
261-
if pkt != nil {
262-
afterTimestamp = pkt.Timestamp
253+
if s.buffer[i] != nil {
254+
afterTimestamp = s.buffer[i].Timestamp
263255
break
264256
}
265257
}
@@ -269,11 +261,10 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
269261

270262
// prior to decoding all the packets, check if this packet
271263
// would end being disposed anyway
272-
pkt, err := s.buffer.PeekAtSequence(consume.head)
273-
if err == nil && !s.depacketizer.IsPartitionHead(pkt.Payload) {
264+
if !s.depacketizer.IsPartitionHead(s.buffer[consume.head].Payload) {
274265
isPadding := false
275266
for i := consume.head; i != consume.tail; i++ {
276-
if s.lastSampleTimestamp != nil && *s.lastSampleTimestamp == pkt.Timestamp && len(pkt.Payload) == 0 {
267+
if s.lastSampleTimestamp != nil && *s.lastSampleTimestamp == s.buffer[i].Timestamp && len(s.buffer[i].Payload) == 0 {
277268
isPadding = true
278269
}
279270
}
@@ -291,22 +282,16 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
291282
var metadata interface{}
292283
var rtpHeaders []*rtp.Header
293284
for i := consume.head; i != consume.tail; i++ {
294-
pkt, err := s.buffer.PeekAtSequence(i)
295-
if err != nil {
296-
return nil
297-
}
298-
p, err := s.depacketizer.Unmarshal(pkt.Payload)
285+
p, err := s.depacketizer.Unmarshal(s.buffer[i].Payload)
299286
if err != nil {
300287
return nil
301288
}
302289
if i == consume.head && s.packetHeadHandler != nil {
303290
metadata = s.packetHeadHandler(s.depacketizer)
304291
}
305292
if s.returnRTPHeaders {
306-
if packet, _ := s.buffer.PeekAtSequence(i); packet != nil {
307-
h := pkt.Header.Clone()
308-
rtpHeaders = append(rtpHeaders, &h)
309-
}
293+
h := s.buffer[i].Header.Clone()
294+
rtpHeaders = append(rtpHeaders, &h)
310295
}
311296

312297
data = append(data, p...)
@@ -404,11 +389,3 @@ func WithRTPHeaders(enable bool) Option {
404389
o.returnRTPHeaders = enable
405390
}
406391
}
407-
408-
// WithJitterBufferMinimumLength sets the minimum number of packets which must first
409-
// be received before starting any playback
410-
func WithJitterBufferMinimumLength(length uint16) Option {
411-
return func(o *SampleBuilder) {
412-
o.buffer = jitterbuffer.New(jitterbuffer.WithMinimumPacketCount(length))
413-
}
414-
}

pkg/media/samplebuilder/samplebuilder_test.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -396,18 +396,14 @@ func TestSampleBuilderCleanReference(t *testing.T) {
396396
s.Push(pkt5)
397397

398398
for i := 0; i < 3; i++ {
399-
pkt, err := s.buffer.PeekAtSequence(uint16((i + int(seqStart)) % 0x10000))
400-
401-
if pkt != nil || err == nil {
399+
if s.buffer[(i+int(seqStart))%0x10000] != nil {
402400
t.Errorf("Old packet (%d) is not unreferenced (maxLate: 10, pushed: 12)", i)
403401
}
404402
}
405-
pkt, err := s.buffer.PeekAtSequence(uint16((14 + int(seqStart)) % 0x10000))
406-
if pkt != pkt4 || err != nil {
403+
if s.buffer[(14+int(seqStart))%0x10000] != pkt4 {
407404
t.Error("New packet must be referenced after jump")
408405
}
409-
pkt, err = s.buffer.PeekAtSequence(uint16((12 + int(seqStart)) % 0x10000))
410-
if pkt != pkt5 || err != nil {
406+
if s.buffer[(12+int(seqStart))%0x10000] != pkt5 {
411407
t.Error("New packet must be referenced after jump")
412408
}
413409
})

0 commit comments

Comments
 (0)