-
Notifications
You must be signed in to change notification settings - Fork 2
/
ts.go
180 lines (148 loc) · 4.4 KB
/
ts.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package mpegts
const (
SyncByte uint8 = 0x47
PacketSize int = 188
)
// ISO/IEC 13818-1 : 2.4.3 Specification of the Transport Stream syntax and semantics
type TS []byte
type ScramblingControl byte
const (
NotScrambled ScramblingControl = 0
ScrambledEvenKey ScramblingControl = 2 // 10
ScrambledOddKey ScramblingControl = 3 // 11
)
var NullTS = TS{
0x47, 0x1F, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
}
// NewTS allocates new TS packet. Sets sync byte and PID
func NewTS(pid PID) TS {
ts := make(TS, PacketSize)
ts[0] = SyncByte
ts.SetPID(pid)
return ts
}
// PID returns packet identifier value.
// PID is a 13-bit field that identifies the payload carried in the packet.
func (p TS) PID() PID {
return getPID(p[1:])
}
// SetPID sets PID in packet
func (p TS) SetPID(pid PID) {
setPID(p[1:], pid)
}
// CC returns continuity counter value.
// Continuity Counter is a 4-bit field incrementing by 1 for each packet
// with payload on the same PID.
func (p TS) CC() uint8 {
return p[3] & 0x0F
}
// SetCC sets continuity counter in packet
func (p TS) SetCC(cc uint8) {
p[3] = (p[3] & 0xF0) | (cc & 0x0F)
}
// IncrementCC increments continuity counter in packet
func (p TS) IncrementCC() {
cc := p.CC() + 1
p.SetCC(cc)
}
// CheckCC checks continuity counter
// Returns current CC and true if CC is equal to expected value
func (p TS) CheckCC(previous uint8) (uint8, bool) {
cc := p.CC()
expected := (previous + 1) & 0x0F
return cc, cc == expected
}
// HasPayload checks is packet has payload
func (p TS) HasPayload() bool {
return (p[3] & 0x10) != 0
}
// SetPayload sets Payload bit
func (p TS) SetPayload() {
p[3] |= 0x10
}
// HasPUSI checks is payload starts in the packet (Payload Unit Start Indicator)
func (p TS) HasPUSI() bool {
return (p[1] & 0x40) != 0
}
// SetPUSI sets Payload Unit Start Indicator bit
func (p TS) SetPUSI() {
p[1] |= 0x40
}
// ClearPUSI clears Payload Unit Start Indicator bit
func (p TS) ClearPUSI() {
p[1] &^= 0x40
}
// HeaderSize returns size of packet header
func (p TS) HeaderSize() int {
if !p.HasAF() {
return 4
} else {
return 4 + 1 + int(p[4])
}
}
// Payload returns payload if available
func (p TS) Payload() []byte {
if !p.HasPayload() || p.HasTEI() {
return nil
}
s := p.HeaderSize()
if s >= PacketSize {
return nil
}
return p[s:PacketSize]
}
// HasTEI checks the Transport Error Indicator bit
func (p TS) HasTEI() bool {
return (p[1] & 0x80) != 0
}
// HasAF checks the Adaptation Field bit
func (p TS) HasAF() bool {
return (p[3] & 0x20) != 0
}
// SetAF sets Adaptation Field bit
func (p TS) SetAF() {
p[3] |= 0x20
}
// ClearAF clears the Adaptation Field bit
func (p TS) ClearAF() {
p[3] &^= 0x20
}
// TSC returns 2-bit Transport Scrambling Control field
func (p TS) TSC() ScramblingControl {
if (p[3] & 0x80) != 0 {
return ScramblingControl((p[3] & 0xC0) >> 6)
} else {
return NotScrambled
}
}
// Fill fills incomplete TS packet with adaptation field stuffing bytes
func (p TS) Fill(size int) {
headerSize := p.HeaderSize()
payloadSize := size - headerSize
offset := PacketSize - payloadSize
copy(p[offset:], p[headerSize:size])
if headerSize == 4 {
// Set adaptation field
p[3] |= 0x20
headerSize += 1
if headerSize < offset {
p[5] = 0x00
headerSize += 1
}
}
for i := headerSize; i < offset; i++ {
p[i] = 0xFF
}
p[4] = byte(PacketSize - 4 - 1 - payloadSize)
}