vendor.github.com.pion.rtp.abssendtimeextension.go Maven / Gradle / Ivy
package rtp
import (
"time"
)
const (
absSendTimeExtensionSize = 3
)
// AbsSendTimeExtension is a extension payload format in
// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
type AbsSendTimeExtension struct {
Timestamp uint64
}
// Marshal serializes the members to buffer.
func (t AbsSendTimeExtension) Marshal() ([]byte, error) {
return []byte{
byte(t.Timestamp & 0xFF0000 >> 16),
byte(t.Timestamp & 0xFF00 >> 8),
byte(t.Timestamp & 0xFF),
}, nil
}
// Unmarshal parses the passed byte slice and stores the result in the members.
func (t *AbsSendTimeExtension) Unmarshal(rawData []byte) error {
if len(rawData) < absSendTimeExtensionSize {
return errTooSmall
}
t.Timestamp = uint64(rawData[0])<<16 | uint64(rawData[1])<<8 | uint64(rawData[2])
return nil
}
// Estimate absolute send time according to the receive time.
// Note that if the transmission delay is larger than 64 seconds, estimated time will be wrong.
func (t *AbsSendTimeExtension) Estimate(receive time.Time) time.Time {
receiveNTP := toNtpTime(receive)
ntp := receiveNTP&0xFFFFFFC000000000 | (t.Timestamp&0xFFFFFF)<<14
if receiveNTP < ntp {
// Receive time must be always later than send time
ntp -= 0x1000000 << 14
}
return toTime(ntp)
}
// NewAbsSendTimeExtension makes new AbsSendTimeExtension from time.Time.
func NewAbsSendTimeExtension(sendTime time.Time) *AbsSendTimeExtension {
return &AbsSendTimeExtension{
Timestamp: toNtpTime(sendTime) >> 14,
}
}
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
}
func toTime(t uint64) time.Time {
s := t >> 32
f := t & 0xFFFFFFFF
f *= 1e9
f >>= 32
s -= 0x83AA7E80
u := s*1e9 + f
return time.Unix(0, int64(u))
}