File: abssendtimeextension.go

package info (click to toggle)
golang-github-pion-rtp 1.7.13-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-backports, forky, sid, trixie
  • size: 472 kB
  • sloc: makefile: 2
file content (78 lines) | stat: -rw-r--r-- 1,869 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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))
}