mirror of https://bitbucket.org/ausocean/av.git
psi: starting to write read functions for psi and tss
This commit is contained in:
parent
ba35615964
commit
2ffa0f9b7b
|
@ -5,6 +5,7 @@ import (
|
|||
"math/bits"
|
||||
)
|
||||
|
||||
// Some common lengths
|
||||
const (
|
||||
ESSDDefLen = 5
|
||||
DescDefLen = 2
|
||||
|
@ -14,26 +15,32 @@ const (
|
|||
PSIDefLen = 3
|
||||
)
|
||||
|
||||
// Table Type IDs
|
||||
const (
|
||||
PATTableID = 0x00
|
||||
PMTTableID = 0x02
|
||||
)
|
||||
|
||||
// Program specific information
|
||||
type PSI struct {
|
||||
pf byte // Point field
|
||||
pfb []byte // Pointer filler bytes
|
||||
tid byte // Table ID
|
||||
ssi bool // Section syntax indicator (1 for PAT, PMT, CAT)
|
||||
pb bool // Private bit (0 for PAT, PMT, CAT)
|
||||
sl uint16 // Section length
|
||||
tss *TSS // Table syntax section (length defined by SL) if length 0 then nil
|
||||
crc uint32 // crc32 of entire table excluding pointer field, pointer filler bytes and the trailing CRC32
|
||||
Pf byte // Point field
|
||||
Pfb []byte // Pointer filler bytes
|
||||
Tid byte // Table ID
|
||||
Ssi bool // Section syntax indicator (1 for PAT, PMT, CAT)
|
||||
Pb bool // Private bit (0 for PAT, PMT, CAT)
|
||||
Sl uint16 // Section length
|
||||
Tss *TSS // Table syntax section (length defined by SL) if length 0 then nil
|
||||
Crc uint32 // crc32 of entire table excluding pointer field, pointer filler bytes and the trailing CRC32
|
||||
}
|
||||
|
||||
// Table syntax section
|
||||
type TSS struct {
|
||||
tide uint16 // Table ID extension
|
||||
v byte // Version number
|
||||
cni bool // Current/next indicator
|
||||
sn byte // Section number
|
||||
lsn byte // Last section number
|
||||
sd SD // Specific data PAT/PMT
|
||||
Tide uint16 // Table ID extension
|
||||
V byte // Version number
|
||||
Cni bool // Current/next indicator
|
||||
Sn byte // Section number
|
||||
Lsn byte // Last section number
|
||||
Sd SD // Specific data PAT/PMT
|
||||
}
|
||||
|
||||
// Specific Data, (could be PAT or PMT)
|
||||
|
@ -43,49 +50,92 @@ type SD interface {
|
|||
|
||||
// Program association table, implements SD
|
||||
type PAT struct {
|
||||
pn uint16 // Program Number
|
||||
pmpid uint16 // Program map PID
|
||||
Pn uint16 // Program Number
|
||||
Pmpid uint16 // Program map PID
|
||||
}
|
||||
|
||||
// Program mapping table, implements SD
|
||||
type PMT struct {
|
||||
pcrpid uint16 // Program clock reference pid
|
||||
pil uint16 // Program info length
|
||||
pd []Desc // Program descriptors
|
||||
essd []ESSD // Elementary stream specific data
|
||||
Pcrpid uint16 // Program clock reference pid
|
||||
Pil uint16 // Program info length
|
||||
Pd []Desc // Program descriptors
|
||||
Essd []ESSD // Elementary stream specific data
|
||||
}
|
||||
|
||||
// Elementary stream specific data
|
||||
type ESSD struct {
|
||||
st byte // Stream type
|
||||
epid uint16 // Elementary pid
|
||||
esil uint16 // Elementary stream
|
||||
esd []Desc // Elementary stream desriptors
|
||||
St byte // Stream type
|
||||
Epid uint16 // Elementary pid
|
||||
Esil uint16 // Elementary stream
|
||||
Esd []Desc // Elementary stream desriptors
|
||||
}
|
||||
|
||||
// Descriptor
|
||||
type Desc struct {
|
||||
dt byte // Descriptor tag
|
||||
dl byte // Descriptor length
|
||||
dd []byte // Descriptor data
|
||||
Dt byte // Descriptor tag
|
||||
Dl byte // Descriptor length
|
||||
Dd []byte // Descriptor data
|
||||
}
|
||||
|
||||
// TODO: Implement this
|
||||
// ReadPSI creates a PSI data structure from a given byte slice that represents a PSI
|
||||
func ReadPSI(data []byte) *PSI {
|
||||
psi := PSI{}
|
||||
pos := 0
|
||||
psi.Pf = data[pos]
|
||||
if psi.Pf != 0 {
|
||||
psi.Pfb = make([]byte, 0, psi.Pf)
|
||||
pos++
|
||||
for i := 0; i < int(psi.Pf); i++ {
|
||||
psi.Pfb = append(psi.Pfb, data[pos])
|
||||
pos++
|
||||
}
|
||||
}
|
||||
psi.Tid = data[pos]
|
||||
pos++
|
||||
psi.Ssi = byteToBool(data[pos] & 0x80)
|
||||
psi.Pb = byteToBool(data[pos] & 0x40)
|
||||
psi.Sl = uint16(data[pos]&0x03)<<8 | uint16(data[pos+1])
|
||||
pos += 2
|
||||
psi.Tss = readTSS(data[pos:], &psi)
|
||||
return &psi
|
||||
}
|
||||
|
||||
// ReadTSS creates a TSS data structure from a given byte slice that represents a TSS
|
||||
func readTSS(data []byte, p *PSI) *TSS {
|
||||
tss := TSS{}
|
||||
pos := 0
|
||||
tss.Tide = uint16(data[pos])<<8 | uint16(data[pos+1])
|
||||
pos += 2
|
||||
tss.V = (data[pos] & 0x3e) >> 1
|
||||
tss.Cni = byteToBool(data[pos] & 0x01)
|
||||
pos++
|
||||
tss.Sn = data[pos]
|
||||
pos++
|
||||
tss.Lsn = data[pos]
|
||||
pos++
|
||||
if p.Tid == PATTableID {
|
||||
tss.Sd = readPAT(data, &tss)
|
||||
} else if p.Tid == PMTTableID {
|
||||
tss.Sd = readPMT(data, &tss)
|
||||
} else {
|
||||
panic("Can't yet deal with tables that are not PAT or PMT")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the PSI
|
||||
func (p *PSI) Bytes() []byte {
|
||||
l := 1 + len(p.pfb)
|
||||
l := 1 + len(p.Pfb)
|
||||
out := make([]byte, l+PSIDefLen)
|
||||
out[0] = p.pf
|
||||
for i, b := range p.pfb {
|
||||
out[0] = p.Pf
|
||||
for i, b := range p.Pfb {
|
||||
out[1+i] = b
|
||||
}
|
||||
out[l] = p.tid
|
||||
out[l+1] = 0x80 | 0x40 | 0x30 | (0x03 & byte(p.sl>>8))
|
||||
out[l+2] = byte(p.sl)
|
||||
out = append(out, p.tss.Bytes()...)
|
||||
out[l] = p.Tid
|
||||
out[l+1] = 0x80 | 0x40 | 0x30 | (0x03 & byte(p.Sl>>8))
|
||||
out[l+2] = byte(p.Sl)
|
||||
out = append(out, p.Tss.Bytes()...)
|
||||
crc32 := crc32_Update(0xffffffff, crc32_MakeTable(bits.Reverse32(crc32.IEEE)), out[l:])
|
||||
out = append(out, make([]byte, 0, 4)...)
|
||||
out = append(out, byte(crc32>>24))
|
||||
|
@ -95,57 +145,62 @@ func (p *PSI) Bytes() []byte {
|
|||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the TSS
|
||||
func (t *TSS) Bytes() []byte {
|
||||
out := make([]byte, TSSDefLen)
|
||||
out[0] = byte(t.tide >> 8)
|
||||
out[1] = byte(t.tide)
|
||||
out[2] = 0xc0 | (0x3e & (t.v << 1)) | (0x01 & boolToByte(t.cni))
|
||||
out[3] = t.sn
|
||||
out[4] = t.lsn
|
||||
out = append(out, t.sd.Bytes()...)
|
||||
out[0] = byte(t.Tide >> 8)
|
||||
out[1] = byte(t.Tide)
|
||||
out[2] = 0xc0 | (0x3e & (t.V << 1)) | (0x01 & boolToByte(t.Cni))
|
||||
out[3] = t.Sn
|
||||
out[4] = t.Lsn
|
||||
out = append(out, t.Sd.Bytes()...)
|
||||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the PAT
|
||||
func (p *PAT) Bytes() []byte {
|
||||
out := make([]byte, PATLen)
|
||||
out[0] = byte(p.pn >> 8)
|
||||
out[1] = byte(p.pn)
|
||||
out[2] = 0xe0 | (0x1f & byte(p.pmpid>>8))
|
||||
out[3] = byte(p.pmpid)
|
||||
out[0] = byte(p.Pn >> 8)
|
||||
out[1] = byte(p.Pn)
|
||||
out[2] = 0xe0 | (0x1f & byte(p.Pmpid>>8))
|
||||
out[3] = byte(p.Pmpid)
|
||||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the PMT
|
||||
func (p *PMT) Bytes() []byte {
|
||||
out := make([]byte, PMTDefLen)
|
||||
out[0] = 0xe0 | (0x1f & byte(p.pcrpid>>8))
|
||||
out[1] = byte(p.pcrpid)
|
||||
out[2] = 0xf0 | (0x03 & byte(p.pil>>8))
|
||||
out[3] = byte(p.pil)
|
||||
for _, d := range p.pd {
|
||||
out[0] = 0xe0 | (0x1f & byte(p.Pcrpid>>8))
|
||||
out[1] = byte(p.Pcrpid)
|
||||
out[2] = 0xf0 | (0x03 & byte(p.Pil>>8))
|
||||
out[3] = byte(p.Pil)
|
||||
for _, d := range p.Pd {
|
||||
out = append(out, d.Bytes()...)
|
||||
}
|
||||
for _, e := range p.essd {
|
||||
for _, e := range p.Essd {
|
||||
out = append(out, e.Bytes()...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the Desc
|
||||
func (d *Desc) Bytes() []byte {
|
||||
out := make([]byte, DescDefLen)
|
||||
out[0] = d.dt
|
||||
out[1] = d.dl
|
||||
out = append(out, d.dd...)
|
||||
out[0] = d.Dt
|
||||
out[1] = d.Dl
|
||||
out = append(out, d.Dd...)
|
||||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the ESSD
|
||||
func (e *ESSD) Bytes() []byte {
|
||||
out := make([]byte, ESSDDefLen)
|
||||
out[0] = e.st
|
||||
out[1] = 0xe0 | (0x1f & byte(e.epid>>8))
|
||||
out[2] = byte(e.epid)
|
||||
out[3] = 0xf0 | (0x03 & byte(e.esil>>8))
|
||||
out[4] = byte(e.esil)
|
||||
for _, d := range e.esd {
|
||||
out[0] = e.St
|
||||
out[1] = 0xe0 | (0x1f & byte(e.Epid>>8))
|
||||
out[2] = byte(e.Epid)
|
||||
out[3] = 0xf0 | (0x03 & byte(e.Esil>>8))
|
||||
out[4] = byte(e.Esil)
|
||||
for _, d := range e.Esd {
|
||||
out = append(out, d.Bytes()...)
|
||||
}
|
||||
return out
|
||||
|
@ -158,6 +213,13 @@ func boolToByte(b bool) byte {
|
|||
return 0x00
|
||||
}
|
||||
|
||||
func byteToBool(b byte) bool {
|
||||
if b == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func crc32_MakeTable(poly uint32) *crc32.Table {
|
||||
var t crc32.Table
|
||||
for i := range t {
|
||||
|
|
Loading…
Reference in New Issue