cloud-game/vendor/github.com/pion/rtp/packetizer.go

118 lines
3 KiB
Go

package rtp
import (
"math/rand"
"time"
)
// Payloader payloads a byte array for use as rtp.Packet payloads
type Payloader interface {
Payload(mtu int, payload []byte) [][]byte
}
// Packetizer packetizes a payload
type Packetizer interface {
Packetize(payload []byte, samples uint32) []*Packet
EnableAbsSendTime(value int)
}
type packetizer struct {
MTU int
PayloadType uint8
SSRC uint32
Payloader Payloader
Sequencer Sequencer
Timestamp uint32
ClockRate uint32
extensionNumbers struct { //put extension numbers in here. If they're 0, the extension is disabled (0 is not a legal extension number)
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 int, pt uint8, ssrc uint32, payloader Payloader, sequencer Sequencer, clockRate uint32) Packetizer {
rs := rand.NewSource(time.Now().UnixNano())
r := rand.New(rs)
return &packetizer{
MTU: mtu,
PayloadType: pt,
SSRC: ssrc,
Payloader: payloader,
Sequencer: sequencer,
Timestamp: r.Uint32(),
ClockRate: clockRate,
timegen: time.Now,
}
}
func (p *packetizer) EnableAbsSendTime(value int) {
p.extensionNumbers.AbsSendTime = value
}
func toNtpTime(t time.Time) uint64 {
var s uint64
var f uint64
u := uint64(t.UnixNano())
s = u / 1e9
s += 0x83AA7E80 //offset in seconds between unix epoch and ntp epoch
f = u % 1e9
f <<= 32
f /= 1e9
s <<= 32
return s | f
}
// 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,
},
Payload: pp,
}
}
p.Timestamp += samples
if len(packets) != 0 && p.extensionNumbers.AbsSendTime != 0 {
t := toNtpTime(p.timegen()) >> 14
//apply http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
packets[len(packets)-1].Header.Extension = true
packets[len(packets)-1].ExtensionProfile = 0xBEDE
packets[len(packets)-1].ExtensionPayload = []byte{
//the first byte is
// 0 1 2 3 4 5 6 7
//+-+-+-+-+-+-+-+-+
//| ID | len |
//+-+-+-+-+-+-+-+-+
//per RFC 5285
//Len is the number of bytes in the extension - 1
byte((p.extensionNumbers.AbsSendTime << 4) | 2),
byte(t & 0xFF0000 >> 16),
byte(t & 0xFF00 >> 8),
byte(t & 0xFF),
}
}
return packets
}