mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-07-22 17:47:11 +00:00
118 lines
3 KiB
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
|
|
}
|