/* NAME psi.go DESCRIPTION See Readme.md AUTHOR Saxon Milton LICENSE psi.go is Copyright (C) 2018 the Australian Ocean Lab (AusOcean) It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with revid in gpl.txt. If not, see http://www.gnu.org/licenses. */ package psi // Lengths of section definitions const ( ESSDDefLen = 5 DescDefLen = 2 PMTDefLen = 4 PATLen = 4 TSSDefLen = 5 PSIDefLen = 3 ) // Table Type IDs const ( patID = 0x00 pmtID = 0x02 ) // Consts relating to time description const ( TimeDescTag = 234 TimeTagIndx = 13 TimeDataIndx = 15 TimeDataSize = 8 // bytes, because time is stored in uint64 ) // Consts relating to location description const ( LocationDescTag = 235 LocationTagIndx = 23 LocationDataIndx = 25 LocationDataSize = 32 // bytes ) // 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 } // 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 SpecificData // Specific data PAT/PMT } // Specific Data, (could be PAT or PMT) type SpecificData interface { Bytes() []byte } // Program association table, implements SpecificData type PAT struct { Pn uint16 // Program Number Pmpid uint16 // Program map PID } // Program mapping table, implements SpecificData type PMT struct { 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 } // Descriptor type Desc struct { Dt byte // Descriptor tag Dl byte // Descriptor length Dd []byte // Descriptor data } // Bytes outputs a byte slice representation of the PSI func (p *PSI) Bytes() []byte { out := make([]byte, 4) out[0] = p.Pf if p.Pf != 0 { panic("No support for pointer filler bytes") } out[1] = p.Tid out[2] = 0x80 | 0x30 | (0x03 & byte(p.Sl>>8)) out[3] = byte(p.Sl) out = append(out, p.Tss.Bytes()...) out = addCrc(out) 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 & asByte(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) 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)) // byte 10 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()...) } out = append(out, p.Essd.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...) 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 = append(out, d.Bytes()...) } return out } func asByte(b bool) byte { if b { return 0x01 } return 0x00 }