/
mpegts_pat.go
230 lines (187 loc) · 6.79 KB
/
mpegts_pat.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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package mpegts
import (
"bytes"
"errors"
"fmt"
"io"
"m7s.live/engine/v4/util"
)
// ios13818-1-CN.pdf 43(57)/166
//
// PAT
//
var DefaultPATPacket = []byte{
// TS Header
0x47, 0x40, 0x00, 0x10,
// Pointer Field
0x00,
// PSI
0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00,
// PAT
0x00, 0x01, 0xe1, 0x00,
// CRC
0xe8, 0xf9, 0x5e, 0x7d,
// Stuffing 167 bytes
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,
}
// TS Header :
// SyncByte = 0x47
// TransportErrorIndicator = 0(B:0), PayloadUnitStartIndicator = 1(B:0), TransportPriority = 0(B:0),
// Pid = 0,
// TransportScramblingControl = 0(B:00), AdaptionFieldControl = 1(B:01), ContinuityCounter = 0(B:0000),
// PSI :
// TableID = 0x00,
// SectionSyntaxIndicator = 1(B:1), Zero = 0(B:0), Reserved1 = 3(B:11),
// SectionLength = 13(0x00d)
// TransportStreamID = 0x0001
// Reserved2 = 3(B:11), VersionNumber = (B:00000), CurrentNextIndicator = 1(B:0),
// SectionNumber = 0x00
// LastSectionNumber = 0x00
// PAT :
// ProgramNumber = 0x0001
// Reserved3 = 15(B:1110), ProgramMapPID = 4097(0x1001)
// PAT表主要包含频道号码和每一个频道对应的PMT的PID号码,这些信息我们在处理PAT表格的时候会保存起来,以后会使用到这些数据
type MpegTsPATProgram struct {
ProgramNumber uint16 // 16 bit 节目号
Reserved3 byte // 3 bits 保留位
NetworkPID uint16 // 13 bits 网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID
ProgramMapPID uint16 // 13 bit 节目映射表的PID,节目号大于0时对应的PID.每个节目对应一个
}
// Program Association Table (节目关联表)
// 节目号为0x0000时,表示这是NIT,PID=0x001f,即3.
// 节目号为0x0001时,表示这是PMT,PID=0x100,即256
type MpegTsPAT struct {
// PSI
TableID byte // 8 bits 0x00->PAT,0x02->PMT
SectionSyntaxIndicator byte // 1 bit 段语法标志位,固定为1
Zero byte // 1 bit 0
Reserved1 byte // 2 bits 保留位
SectionLength uint16 // 12 bits 该字段的头两比特必为'00',剩余 10 比特指定该分段的字节数,紧随 section_length 字段开始,并包括 CRC.此字段中的值应不超过 1021(0x3FD)
TransportStreamID uint16 // 16 bits 该字段充当标签,标识网络内此传输流有别于任何其他多路复用流.其值由用户规定
Reserved2 byte // 2 bits 保留位
VersionNumber byte // 5 bits 范围0-31,表示PAT的版本号
CurrentNextIndicator byte // 1 bit 发送的PAT是当前有效还是下一个PAT有效,0则要等待下一个表
SectionNumber byte // 8 bits 分段的号码.PAT可能分为多段传输.第一段为00,以后每个分段加1,最多可能有256个分段
LastSectionNumber byte // 8 bits 最后一个分段的号码
// N Loop
Program []MpegTsPATProgram // PAT表里面的所有频道索引信息
Crc32 uint32 // 32 bits 包含处理全部传输流节目映射分段之后,在附件 B 规定的解码器中给出寄存器零输出的 CRC 值
}
func ReadPAT(r io.Reader) (pat MpegTsPAT, err error) {
lr, psi, err := ReadPSI(r, PSI_TYPE_PAT)
if err != nil {
return
}
pat = psi.Pat
// N Loop
// 一直循环去读4个字节,用lr的原因是确保不会读过头了.
for lr.N > 0 {
// 获取每一个频道的节目信息,保存起来
programs := MpegTsPATProgram{}
programs.ProgramNumber, err = util.ReadByteToUint16(lr, true)
if err != nil {
return
}
// 如果programNumber为0,则是NetworkPID,否则是ProgramMapPID(13)
if programs.ProgramNumber == 0 {
programs.NetworkPID, err = util.ReadByteToUint16(lr, true)
if err != nil {
return
}
programs.NetworkPID = programs.NetworkPID & 0x1fff
} else {
programs.ProgramMapPID, err = util.ReadByteToUint16(lr, true)
if err != nil {
return
}
programs.ProgramMapPID = programs.ProgramMapPID & 0x1fff
}
pat.Program = append(pat.Program, programs)
}
if cr, ok := r.(*util.Crc32Reader); ok {
err = cr.ReadCrc32UIntAndCheck()
if err != nil {
return
}
}
return
}
func WritePAT(w io.Writer, pat MpegTsPAT) (err error) {
bw := &bytes.Buffer{}
// 将pat(所有的节目索引信息)写入到缓冲区中
for _, pats := range pat.Program {
if err = util.WriteUint16ToByte(bw, pats.ProgramNumber, true); err != nil {
return
}
if pats.ProgramNumber == 0 {
if err = util.WriteUint16ToByte(bw, pats.NetworkPID&0x1fff|7<<13, true); err != nil {
return
}
} else {
// | 0001 1111 | 1111 1111 |
// 7 << 13 -> 1110 0000 0000 0000
if err = util.WriteUint16ToByte(bw, pats.ProgramMapPID&0x1fff|7<<13, true); err != nil {
return
}
}
}
if pat.SectionLength == 0 {
pat.SectionLength = 2 + 3 + 4 + uint16(len(bw.Bytes()))
}
psi := MpegTsPSI{}
psi.Pat = pat
if err = WritePSI(w, PSI_TYPE_PAT, psi, bw.Bytes()); err != nil {
return
}
return
}
func WritePATPacket(w io.Writer, tsHeader []byte, pat MpegTsPAT) (err error) {
if pat.TableID != TABLE_PAS {
err = errors.New("PAT table ID error")
return
}
// 将所有要写的数据(PAT),全部放入到buffer中去.
// buffer 里面已经写好了整个pat表(PointerField+PSI+PAT+CRC)
bw := &bytes.Buffer{}
if err = WritePAT(bw, pat); err != nil {
return
}
// TODO:如果Pat.Program里面包含的信息很大,大于188?
stuffingBytes := util.GetFillBytes(0xff, TS_PACKET_SIZE-4-bw.Len())
// PATPacket = TsHeader + PAT + Stuffing Bytes
var PATPacket []byte
PATPacket = append(PATPacket, tsHeader...)
PATPacket = append(PATPacket, bw.Bytes()...)
PATPacket = append(PATPacket, stuffingBytes...)
fmt.Println("-------------------------")
fmt.Println("Write PAT :", PATPacket)
fmt.Println("-------------------------")
// 写PAT负载
if _, err = w.Write(PATPacket); err != nil {
return
}
return
}
func WriteDefaultPATPacket(w io.Writer) (err error) {
_, err = w.Write(DefaultPATPacket)
if err != nil {
return
}
return
}