/
timestamp.go
94 lines (75 loc) · 1.94 KB
/
timestamp.go
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package ts
import (
"time"
)
const (
// Program Clock Reference (PCR) is based on a 27 Mhz clock
PCRFrequency = uint64(27000000)
// Presentation Time Stamp (PTS) is based on a 90khz clock
PTSFrequency = uint64(90000)
)
type TimeStamp interface {
Ticks() uint64
Increment(ticks uint64)
Duration() time.Duration
Delta(endTs TimeStamp) TimeStamp
}
func CalculatePCR(b []byte) TimeStamp {
base := uint64(b[0]) << 25
base |= uint64(b[1]) << 17
base |= uint64(b[2]) << 9
base |= uint64(b[3]) << 1
base |= uint64(b[4]&0x80) >> 7
extension := uint64(b[4]&0x01) << 8
extension |= uint64(b[5])
pcr := NewPCR()
pcr.Increment(base*300 + extension)
return pcr
}
func CalculatePTS(b []byte) TimeStamp {
ticks := uint64(b[0]>>1&0x07) << 30
ticks |= uint64(b[1]) << 22
ticks |= uint64(b[2]>>1&0x7f) << 15
ticks |= uint64(b[3]) << 7
ticks |= uint64(b[4] >> 1 & 0x7f)
pts := NewPTS()
pts.Increment(ticks)
return pts
}
func DumpPTS(timestamp TimeStamp) []byte {
output := make([]byte, 5)
ticks := timestamp.Ticks()
output[0] = byte(ticks>>30) & 0x07
output[1] = byte(ticks >> 22)
output[2] = byte(ticks>>15)<<1 | 0x01
output[3] = byte(ticks >> 7)
output[4] = byte(ticks)<<1 | 0x01
return output
}
var CalculateDTS = CalculatePTS
var CalculateESCR = CalculatePTS
func NewPCR() TimeStamp {
return newTimestamp(0, PCRFrequency)
}
func NewPTS() TimeStamp {
return newTimestamp(0, PTSFrequency)
}
func newTimestamp(ticks uint64, frequency uint64) *timestamp {
return ×tamp{ticks, 1000000000 / frequency}
}
type timestamp struct {
ticks uint64
interval uint64 // number of nanoseconds in one period
}
func (t *timestamp) Increment(ticks uint64) {
t.ticks += ticks
}
func (t *timestamp) Ticks() uint64 {
return t.ticks
}
func (t *timestamp) Duration() time.Duration {
return time.Duration(t.ticks * t.interval)
}
func (t *timestamp) Delta(endTs TimeStamp) TimeStamp {
return ×tamp{0x3fffffffff & (endTs.Ticks() - t.ticks), t.interval}
}