2018-12-12 02:48:05 +03:00
|
|
|
/*
|
|
|
|
NAME
|
|
|
|
psi.go
|
|
|
|
DESCRIPTION
|
|
|
|
See Readme.md
|
|
|
|
|
|
|
|
AUTHOR
|
|
|
|
Saxon Milton <saxon@ausocean.org>
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2018-12-04 08:33:04 +03:00
|
|
|
package psi
|
|
|
|
|
2018-12-27 05:59:08 +03:00
|
|
|
// Misc consts
|
|
|
|
const (
|
2019-01-02 02:56:34 +03:00
|
|
|
PktSize = 184
|
2018-12-27 05:59:08 +03:00
|
|
|
)
|
|
|
|
|
2018-12-11 09:46:26 +03:00
|
|
|
// Lengths of section definitions
|
2018-12-05 14:16:06 +03:00
|
|
|
const (
|
2018-12-05 17:11:53 +03:00
|
|
|
ESSDDefLen = 5
|
|
|
|
DescDefLen = 2
|
|
|
|
PMTDefLen = 4
|
|
|
|
PATLen = 4
|
2018-12-05 17:58:14 +03:00
|
|
|
TSSDefLen = 5
|
|
|
|
PSIDefLen = 3
|
2018-12-05 14:16:06 +03:00
|
|
|
)
|
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Table Type IDs
|
|
|
|
const (
|
2019-01-08 01:12:30 +03:00
|
|
|
patID = 0x00
|
|
|
|
pmtID = 0x02
|
2018-12-06 06:20:17 +03:00
|
|
|
)
|
|
|
|
|
2018-12-11 09:46:26 +03:00
|
|
|
// Consts relating to time description
|
2018-12-06 08:32:40 +03:00
|
|
|
const (
|
2019-01-07 09:43:50 +03:00
|
|
|
TimeDescTag = 234
|
|
|
|
TimeTagIndx = 13
|
|
|
|
TimeDataIndx = 15
|
|
|
|
TimeDataSize = 8 // bytes, because time is stored in uint64
|
2018-12-12 08:56:59 +03:00
|
|
|
)
|
|
|
|
|
2018-12-14 08:32:47 +03:00
|
|
|
// Consts relating to location description
|
2018-12-12 08:56:59 +03:00
|
|
|
const (
|
2019-01-07 09:43:50 +03:00
|
|
|
LocationDescTag = 235
|
|
|
|
LocationTagIndx = 23
|
|
|
|
LocationDataIndx = 25
|
|
|
|
LocationDataSize = 32 // bytes
|
2018-12-06 08:32:40 +03:00
|
|
|
)
|
|
|
|
|
2019-01-03 10:26:08 +03:00
|
|
|
// Other misc consts
|
|
|
|
const (
|
|
|
|
syntaxSecLenIndx = 3
|
|
|
|
crcSize = 4
|
|
|
|
)
|
|
|
|
|
2018-12-04 08:33:04 +03:00
|
|
|
// Program specific information
|
|
|
|
type PSI struct {
|
2018-12-06 06:20:17 +03:00
|
|
|
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
|
2018-12-04 08:33:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Table syntax section
|
|
|
|
type TSS struct {
|
2019-01-07 08:57:18 +03:00
|
|
|
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
|
2018-12-04 08:33:04 +03:00
|
|
|
}
|
|
|
|
|
2018-12-05 12:01:29 +03:00
|
|
|
// Specific Data, (could be PAT or PMT)
|
2019-01-07 08:57:18 +03:00
|
|
|
type SpecificData interface {
|
2018-12-05 12:01:29 +03:00
|
|
|
Bytes() []byte
|
2018-12-04 08:33:04 +03:00
|
|
|
}
|
|
|
|
|
2019-01-07 08:57:18 +03:00
|
|
|
// Program association table, implements SpecificData
|
2018-12-05 12:01:29 +03:00
|
|
|
type PAT struct {
|
2018-12-06 06:20:17 +03:00
|
|
|
Pn uint16 // Program Number
|
|
|
|
Pmpid uint16 // Program map PID
|
2018-12-05 14:16:06 +03:00
|
|
|
}
|
|
|
|
|
2019-01-07 08:57:18 +03:00
|
|
|
// Program mapping table, implements SpecificData
|
2018-12-05 14:16:06 +03:00
|
|
|
type PMT struct {
|
2018-12-06 06:20:17 +03:00
|
|
|
Pcrpid uint16 // Program clock reference pid
|
|
|
|
Pil uint16 // Program info length
|
|
|
|
Pd []Desc // Program descriptors
|
2018-12-07 08:23:38 +03:00
|
|
|
Essd *ESSD // Elementary stream specific data
|
2018-12-04 08:33:04 +03:00
|
|
|
}
|
|
|
|
|
2018-12-05 14:16:06 +03:00
|
|
|
// Elementary stream specific data
|
|
|
|
type ESSD struct {
|
2018-12-06 06:20:17 +03:00
|
|
|
St byte // Stream type
|
|
|
|
Epid uint16 // Elementary pid
|
|
|
|
Esil uint16 // Elementary stream
|
|
|
|
Esd []Desc // Elementary stream desriptors
|
2018-12-05 14:16:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Descriptor
|
|
|
|
type Desc struct {
|
2018-12-06 06:20:17 +03:00
|
|
|
Dt byte // Descriptor tag
|
|
|
|
Dl byte // Descriptor length
|
|
|
|
Dd []byte // Descriptor data
|
2018-12-05 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Bytes outputs a byte slice representation of the PSI
|
2018-12-05 17:58:14 +03:00
|
|
|
func (p *PSI) Bytes() []byte {
|
2018-12-11 07:22:18 +03:00
|
|
|
out := make([]byte, 4)
|
2018-12-06 06:20:17 +03:00
|
|
|
out[0] = p.Pf
|
2018-12-11 07:22:18 +03:00
|
|
|
if p.Pf != 0 {
|
|
|
|
panic("No support for pointer filler bytes")
|
2018-12-05 17:58:14 +03:00
|
|
|
}
|
2018-12-11 07:22:18 +03:00
|
|
|
out[1] = p.Tid
|
|
|
|
out[2] = 0x80 | 0x30 | (0x03 & byte(p.Sl>>8))
|
|
|
|
out[3] = byte(p.Sl)
|
2018-12-06 06:20:17 +03:00
|
|
|
out = append(out, p.Tss.Bytes()...)
|
2018-12-13 07:39:23 +03:00
|
|
|
out = addCrc(out)
|
2018-12-27 06:41:23 +03:00
|
|
|
out = addPadding(out)
|
2018-12-06 04:46:26 +03:00
|
|
|
return out
|
2018-12-05 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Bytes outputs a byte slice representation of the TSS
|
2018-12-05 17:58:14 +03:00
|
|
|
func (t *TSS) Bytes() []byte {
|
|
|
|
out := make([]byte, TSSDefLen)
|
2018-12-06 06:20:17 +03:00
|
|
|
out[0] = byte(t.Tide >> 8)
|
|
|
|
out[1] = byte(t.Tide)
|
2019-01-07 09:00:48 +03:00
|
|
|
out[2] = 0xc0 | (0x3e & (t.V << 1)) | (0x01 & asByte(t.Cni))
|
2018-12-06 06:20:17 +03:00
|
|
|
out[3] = t.Sn
|
|
|
|
out[4] = t.Lsn
|
|
|
|
out = append(out, t.Sd.Bytes()...)
|
2018-12-05 17:58:14 +03:00
|
|
|
return out
|
2018-12-05 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Bytes outputs a byte slice representation of the PAT
|
2018-12-05 17:11:53 +03:00
|
|
|
func (p *PAT) Bytes() []byte {
|
|
|
|
out := make([]byte, PATLen)
|
2018-12-06 06:20:17 +03:00
|
|
|
out[0] = byte(p.Pn >> 8)
|
|
|
|
out[1] = byte(p.Pn)
|
|
|
|
out[2] = 0xe0 | (0x1f & byte(p.Pmpid>>8))
|
|
|
|
out[3] = byte(p.Pmpid)
|
2018-12-05 17:11:53 +03:00
|
|
|
return out
|
2018-12-05 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Bytes outputs a byte slice representation of the PMT
|
2018-12-05 17:04:29 +03:00
|
|
|
func (p *PMT) Bytes() []byte {
|
2018-12-05 17:11:53 +03:00
|
|
|
out := make([]byte, PMTDefLen)
|
2018-12-11 08:32:57 +03:00
|
|
|
out[0] = 0xe0 | (0x1f & byte(p.Pcrpid>>8)) // byte 10
|
2018-12-06 06:20:17 +03:00
|
|
|
out[1] = byte(p.Pcrpid)
|
|
|
|
out[2] = 0xf0 | (0x03 & byte(p.Pil>>8))
|
|
|
|
out[3] = byte(p.Pil)
|
|
|
|
for _, d := range p.Pd {
|
2018-12-05 17:04:29 +03:00
|
|
|
out = append(out, d.Bytes()...)
|
|
|
|
}
|
2018-12-06 08:32:40 +03:00
|
|
|
out = append(out, p.Essd.Bytes()...)
|
2018-12-05 17:04:29 +03:00
|
|
|
return out
|
2018-12-05 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Bytes outputs a byte slice representation of the Desc
|
2018-12-05 17:04:29 +03:00
|
|
|
func (d *Desc) Bytes() []byte {
|
2018-12-05 17:11:53 +03:00
|
|
|
out := make([]byte, DescDefLen)
|
2018-12-06 06:20:17 +03:00
|
|
|
out[0] = d.Dt
|
|
|
|
out[1] = d.Dl
|
|
|
|
out = append(out, d.Dd...)
|
2018-12-05 17:04:29 +03:00
|
|
|
return out
|
2018-12-04 08:33:04 +03:00
|
|
|
}
|
2018-12-05 14:16:06 +03:00
|
|
|
|
2018-12-06 06:20:17 +03:00
|
|
|
// Bytes outputs a byte slice representation of the ESSD
|
2018-12-05 17:04:29 +03:00
|
|
|
func (e *ESSD) Bytes() []byte {
|
2018-12-05 17:11:53 +03:00
|
|
|
out := make([]byte, ESSDDefLen)
|
2018-12-06 06:20:17 +03:00
|
|
|
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 {
|
2018-12-05 16:34:19 +03:00
|
|
|
out = append(out, d.Bytes()...)
|
2018-12-05 14:16:06 +03:00
|
|
|
}
|
2018-12-05 17:04:29 +03:00
|
|
|
return out
|
2018-12-05 14:16:06 +03:00
|
|
|
}
|
2018-12-05 17:58:14 +03:00
|
|
|
|
2019-01-08 12:36:07 +03:00
|
|
|
func asByte(b bool) byte {
|
2018-12-05 17:58:14 +03:00
|
|
|
if b {
|
2019-01-08 12:36:07 +03:00
|
|
|
return 0x01
|
2018-12-06 04:46:26 +03:00
|
|
|
}
|
2019-01-08 12:36:07 +03:00
|
|
|
return 0x00
|
2018-12-06 04:46:26 +03:00
|
|
|
}
|