kvm/vendor/github.com/pion/rtp/packetizer.go

195 lines
4.8 KiB
Go

// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package rtp
import (
"time"
)
// Payloader payloads a byte array for use as rtp.Packet payloads.
type Payloader interface {
Payload(mtu uint16, payload []byte) [][]byte
}
// Packetizer packetizes a payload.
type Packetizer interface {
Packetize(payload []byte, samples uint32) []*Packet
GeneratePadding(samples uint32) []*Packet
EnableAbsSendTime(value int)
SkipSamples(skippedSamples uint32)
}
type packetizer struct {
MTU uint16
PayloadType uint8
SSRC uint32
Payloader Payloader
Sequencer Sequencer
Timestamp uint32
// Deprecated: will be removed in a future version.
ClockRate uint32
// put extension numbers in here. If they're 0, the extension is disabled (0 is not a legal extension number)
extensionNumbers struct {
AbsSendTime int // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
}
timegen func() time.Time
}
// NewPacketizer returns a new instance of a Packetizer for a specific payloader.
func NewPacketizer(
mtu uint16,
pt uint8,
ssrc uint32,
payloader Payloader,
sequencer Sequencer,
clockRate uint32,
) Packetizer {
return &packetizer{
MTU: mtu,
PayloadType: pt,
SSRC: ssrc,
Payloader: payloader,
Sequencer: sequencer,
Timestamp: globalMathRandomGenerator.Uint32(),
ClockRate: clockRate,
timegen: time.Now,
}
}
// WithSSRC sets the SSRC for the Packetizer.
func WithSSRC(ssrc uint32) func(*packetizer) {
return func(p *packetizer) {
p.SSRC = ssrc
}
}
// WithPayloadType sets the PayloadType for the Packetizer.
func WithPayloadType(pt uint8) func(*packetizer) {
return func(p *packetizer) {
p.PayloadType = pt
}
}
// WithTimestamp sets the initial Timestamp for the Packetizer.
func WithTimestamp(timestamp uint32) func(*packetizer) {
return func(p *packetizer) {
p.Timestamp = timestamp
}
}
// PacketizerOption is a function that configures a RTP Packetizer.
type PacketizerOption func(*packetizer)
// NewPacketizerWithOptions returns a new instance of a Packetizer with the given options.
func NewPacketizerWithOptions(
mtu uint16,
payloader Payloader,
sequencer Sequencer,
clockRate uint32,
options ...PacketizerOption,
) Packetizer {
packetizerInstance := &packetizer{
MTU: mtu,
Payloader: payloader,
Sequencer: sequencer,
Timestamp: globalMathRandomGenerator.Uint32(),
ClockRate: clockRate,
timegen: time.Now,
}
for _, option := range options {
option(packetizerInstance)
}
return packetizerInstance
}
func (p *packetizer) EnableAbsSendTime(value int) {
p.extensionNumbers.AbsSendTime = value
}
// Packetize packetizes the payload of an RTP packet and returns one or more RTP packets.
func (p *packetizer) Packetize(payload []byte, samples uint32) []*Packet {
// Guard against an empty payload
if len(payload) == 0 {
return nil
}
payloads := p.Payloader.Payload(p.MTU-12, payload)
packets := make([]*Packet, len(payloads))
for i, pp := range payloads {
packets[i] = &Packet{
Header: Header{
Version: 2,
Padding: false,
Extension: false,
Marker: i == len(payloads)-1,
PayloadType: p.PayloadType,
SequenceNumber: p.Sequencer.NextSequenceNumber(),
Timestamp: p.Timestamp, // Figure out how to do timestamps
SSRC: p.SSRC,
CSRC: []uint32{},
},
Payload: pp,
}
}
p.Timestamp += samples
if len(packets) != 0 && p.extensionNumbers.AbsSendTime != 0 {
sendTime := NewAbsSendTimeExtension(p.timegen())
// apply http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
b, err := sendTime.Marshal()
if err != nil {
return nil // never happens
}
err = packets[len(packets)-1].SetExtension(uint8(p.extensionNumbers.AbsSendTime), b) // nolint: gosec // G115
if err != nil {
return nil // never happens
}
}
return packets
}
// GeneratePadding returns required padding-only packages.
func (p *packetizer) GeneratePadding(samples uint32) []*Packet {
// Guard against an empty payload
if samples == 0 {
return nil
}
packets := make([]*Packet, samples)
for i := 0; i < int(samples); i++ {
pp := make([]byte, 255)
pp[254] = 255
packets[i] = &Packet{
Header: Header{
Version: 2,
Padding: true,
Extension: false,
Marker: false,
PayloadType: p.PayloadType,
SequenceNumber: p.Sequencer.NextSequenceNumber(),
Timestamp: p.Timestamp, // Use latest timestamp
SSRC: p.SSRC,
CSRC: []uint32{},
},
Payload: pp,
}
}
return packets
}
// SkipSamples causes a gap in sample count between Packetize requests so the
// RTP payloads produced have a gap in timestamps.
func (p *packetizer) SkipSamples(skippedSamples uint32) {
p.Timestamp += skippedSamples
}