-
Notifications
You must be signed in to change notification settings - Fork 2
/
pat.go
69 lines (62 loc) · 2.07 KB
/
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
package mpeg2ts
import (
"fmt"
)
// Program Association Table
type PAT struct {
Pointer byte
TableID byte
SectionSyntaxIndicator bool
Reserved1 byte
SectionLength uint16
TransportStreamID uint16
Reserved2 int
Version byte
CurrentNextIndicator bool
SectionNumber byte
LastSectionNumber byte
CRC32 uint
Programs []PATProgram
}
type PATProgram struct {
ProgramNumber uint16
Reserved int
NetworkPID PID
ProgramMapPID PID
}
func (p *Packet) ParsePAT() (PAT, error) {
pat := PAT{}
payload, err := p.GetPayload()
if err != nil {
return PAT{}, err
}
pat.Pointer = payload[0]
pat.TableID = payload[1]
pat.SectionSyntaxIndicator = ((payload[2] >> 7) & 0x01) == 1
if ((payload[2] >> 6) & 0x01) == 1 {
return PAT{}, fmt.Errorf("invalid format")
}
pat.SectionLength = uint16(payload[2]&0x0F)<<8 | uint16(payload[3])
pat.TransportStreamID = uint16(payload[4])<<8 | uint16(payload[5])
pat.Version = (payload[6] >> 1) & 0x1F
pat.CurrentNextIndicator = (payload[6] & 0x01) == 0x01
pat.SectionNumber = payload[7]
pat.LastSectionNumber = payload[8]
pat.Programs = make([]PATProgram, (pat.SectionLength-5-4)/4)
for i := uint16(0); i < (pat.SectionLength-5-4)/4; i++ {
base := 9 + i*4
pat.Programs[i].ProgramNumber = uint16(payload[base])<<8 | uint16(payload[base+1])
if pat.Programs[i].ProgramNumber == 0x0000 {
pat.Programs[i].NetworkPID = PID(uint16(payload[base+2]&0x1f)<<8 | uint16(payload[base+3])&0x1fff)
} else {
pat.Programs[i].ProgramMapPID = PID(uint16(payload[base+2]&0x1f)<<8 | uint16(payload[base+3])&0x1fff)
}
}
pat.CRC32 = uint(payload[pat.SectionLength])<<24 | uint(payload[pat.SectionLength+1])<<16 | uint(payload[pat.SectionLength+2])<<8 | uint(payload[pat.SectionLength+3])
crc := calculateCRC(payload[1:pat.SectionLength])
if uint32(pat.CRC32) != crc {
return PAT{}, fmt.Errorf("CRC32 mismatch")
}
// fmt.Println("CRC OK")
return pat, nil
}