Skip to content

Commit 7c60bb9

Browse files
digitalixSean-Der
authored andcommitted
Adds WithPacketHeadHandler to SampleBuilder
This option allows inspecting head packet for each media.Sample and then lets the user return their custom metadata. This might be useful in case when you need to check whether the given sample is a keyframe.
1 parent b40f599 commit 7c60bb9

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

pkg/media/media.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type Sample struct {
1717
Duration time.Duration
1818
PacketTimestamp uint32
1919
PrevDroppedPackets uint16
20+
Metadata interface{}
2021
}
2122

2223
// Writer defines an interface to handle

pkg/media/samplebuilder/samplebuilder.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ type SampleBuilder struct {
4040

4141
// number of packets forced to be dropped
4242
droppedPackets uint16
43+
44+
// allows inspecting head packets of each sample and then returns a custom metadata
45+
packetHeadHandler func(headPacket interface{}) interface{}
4346
}
4447

4548
// New constructs a new SampleBuilder.
@@ -253,11 +256,16 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
253256

254257
// merge all the buffers into a sample
255258
data := []byte{}
259+
var metadata interface{}
256260
for i := consume.head; i != consume.tail; i++ {
257261
p, err := s.depacketizer.Unmarshal(s.buffer[i].Payload)
258262
if err != nil {
259263
return nil
260264
}
265+
if i == consume.head && s.packetHeadHandler != nil {
266+
metadata = s.packetHeadHandler(s.depacketizer)
267+
}
268+
261269
data = append(data, p...)
262270
}
263271
samples := afterTimestamp - sampleTimestamp
@@ -267,6 +275,7 @@ func (s *SampleBuilder) buildSample(purgingBuffers bool) *media.Sample {
267275
Duration: time.Duration((float64(samples)/float64(s.sampleRate))*secondToNanoseconds) * time.Nanosecond,
268276
PacketTimestamp: sampleTimestamp,
269277
PrevDroppedPackets: s.droppedPackets,
278+
Metadata: metadata,
270279
}
271280

272281
s.droppedPackets = 0
@@ -341,6 +350,14 @@ func WithPacketReleaseHandler(h func(*rtp.Packet)) Option {
341350
}
342351
}
343352

353+
// WithPacketHeadHandler set a head packet handler to allow inspecting
354+
// the packet to extract certain information and return as custom metadata
355+
func WithPacketHeadHandler(h func(headPacket interface{}) interface{}) Option {
356+
return func(o *SampleBuilder) {
357+
o.packetHeadHandler = h
358+
}
359+
}
360+
344361
// WithMaxTimeDelay ensures that packets that are too old in the buffer get
345362
// purged based on time rather than building up an extraordinarily long delay.
346363
func WithMaxTimeDelay(maxLateDuration time.Duration) Option {

pkg/media/samplebuilder/samplebuilder_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,38 @@ func TestSampleBuilderWithPacketReleaseHandler(t *testing.T) {
389389
}
390390
}
391391

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+
392424
func TestPopWithTimestamp(t *testing.T) {
393425
t.Run("Crash on nil", func(t *testing.T) {
394426
s := New(0, &fakeDepacketizer{}, 1)

0 commit comments

Comments
 (0)