mirror of https://bitbucket.org/ausocean/av.git
Merged in psi-field-naming (pull request #414)
container/mts/psi: improved PSI structs field naming Approved-by: Trek Hopton <trek.hopton@gmail.com>
This commit is contained in:
parent
90c39db59d
commit
5f5a1d03a1
|
@ -177,8 +177,8 @@ func NewEncoder(dst io.WriteCloser, log logger, options ...func(*Encoder) error)
|
|||
}
|
||||
log.Debug("encoder options applied")
|
||||
|
||||
e.pmt.Tss.Sd.(*psi.PMT).Essd.St = e.streamID
|
||||
e.pmt.Tss.Sd.(*psi.PMT).Essd.Epid = e.mediaPID
|
||||
e.pmt.SyntaxSection.SpecificData.(*psi.PMT).StreamSpecificData.StreamType = e.streamID
|
||||
e.pmt.SyntaxSection.SpecificData.(*psi.PMT).StreamSpecificData.PID = e.mediaPID
|
||||
e.pmtBytes = e.pmt.Bytes()
|
||||
|
||||
return e, nil
|
||||
|
|
|
@ -314,7 +314,7 @@ func TestMetaEncode1(t *testing.T) {
|
|||
0x00, 0x10, 0x00, 0x0b, 't', 's', '=', '1', '2', '3', '4', '5', '6', '7', '8', // timestamp
|
||||
0x1b, 0xe1, 0x00, 0xf0, 0x00,
|
||||
}
|
||||
want = psi.AddCrc(want)
|
||||
want = psi.AddCRC(want)
|
||||
want = psi.AddPadding(want)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("unexpected output. \n Got : %v\n, Want: %v\n", got, want)
|
||||
|
@ -347,7 +347,7 @@ func TestMetaEncode2(t *testing.T) {
|
|||
'l', 'o', 'c', '=', '1', '2', '3', '4', ',', '4', '3', '2', '1', ',', '1', '2', '3', '4', // location
|
||||
0x1b, 0xe1, 0x00, 0xf0, 0x00,
|
||||
}
|
||||
want = psi.AddCrc(want)
|
||||
want = psi.AddCRC(want)
|
||||
want = psi.AddPadding(want)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("did not get expected results.\ngot: %v\nwant: %v\n", got, want)
|
||||
|
|
|
@ -432,7 +432,7 @@ func TestSegmentForMeta(t *testing.T) {
|
|||
|
||||
tests := []struct {
|
||||
metaVals [nPSI]string // This represents the meta value for meta pairs (PAT and PMT)
|
||||
expectIdxs []rng // This gives the expect index ranges for the segments.
|
||||
expectIdxs []rng // This gives the expected index ranges for the segments.
|
||||
}{
|
||||
{
|
||||
metaVals: [nPSI]string{"1", "2", val, val, val, "3", val, val, "4", "4"},
|
||||
|
@ -616,20 +616,20 @@ func TestFindPSI(t *testing.T) {
|
|||
switch pkt {
|
||||
case pat:
|
||||
patTable := (&psi.PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x00,
|
||||
Ssi: true,
|
||||
Pb: false,
|
||||
Sl: 0x0d,
|
||||
Tss: &psi.TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &psi.PAT{
|
||||
Pn: 0x01,
|
||||
Pmpid: pmtPID,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x00,
|
||||
SyntaxIndicator: true,
|
||||
PrivateBit: false,
|
||||
SectionLen: 0x0d,
|
||||
SyntaxSection: &psi.SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &psi.PAT{
|
||||
Program: 0x01,
|
||||
ProgramMapPID: pmtPID,
|
||||
},
|
||||
},
|
||||
}).Bytes()
|
||||
|
@ -647,23 +647,23 @@ func TestFindPSI(t *testing.T) {
|
|||
}
|
||||
case pmt:
|
||||
pmtTable := (&psi.PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &psi.TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &psi.PMT{
|
||||
Pcrpid: 0x0100,
|
||||
Pil: 0,
|
||||
Essd: &psi.ESSD{
|
||||
St: mediaType,
|
||||
Epid: streamPID,
|
||||
Esil: 0x00,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x12,
|
||||
SyntaxSection: &psi.SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &psi.PMT{
|
||||
ProgramClockPID: 0x0100,
|
||||
ProgramInfoLen: 0,
|
||||
StreamSpecificData: &psi.StreamSpecificData{
|
||||
StreamType: mediaType,
|
||||
PID: streamPID,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -716,7 +716,7 @@ func TestFindPSI(t *testing.T) {
|
|||
|
||||
gotIdx, gotStreams, gotMeta, gotErr := FindPSI(clip.Bytes())
|
||||
|
||||
// Check error
|
||||
// Check error.
|
||||
if errors.Cause(gotErr) != test.want.err {
|
||||
t.Errorf("did not get expected error for test %d\nGot: %v\nWant: %v\n", i, gotErr, test.want.err)
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
)
|
||||
|
||||
// addCrc appends a crc table to a given psi table in bytes
|
||||
func AddCrc(out []byte) []byte {
|
||||
func AddCRC(out []byte) []byte {
|
||||
t := make([]byte, len(out)+4)
|
||||
copy(t, out)
|
||||
UpdateCrc(t[1:])
|
||||
|
|
|
@ -39,88 +39,88 @@ const (
|
|||
|
||||
var (
|
||||
tstPsi1 = PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x1c,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100, // wrong
|
||||
Pil: 10,
|
||||
Pd: []Desc{
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x1c,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100, // wrong
|
||||
ProgramInfoLen: 10,
|
||||
Descriptors: []Descriptor{
|
||||
{
|
||||
Dt: TimeDescTag,
|
||||
Dl: TimeDataSize,
|
||||
Dd: make([]byte, TimeDataSize),
|
||||
Tag: TimeDescTag,
|
||||
Len: TimeDataSize,
|
||||
Data: make([]byte, TimeDataSize),
|
||||
},
|
||||
},
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tstPsi2 = PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100,
|
||||
Pil: 0,
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x12,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100,
|
||||
ProgramInfoLen: 0,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tstPsi3 = PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x3e,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100,
|
||||
Pil: PmtTimeLocationPil,
|
||||
Pd: []Desc{
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x3e,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100,
|
||||
ProgramInfoLen: PmtTimeLocationPil,
|
||||
Descriptors: []Descriptor{
|
||||
{
|
||||
Dt: TimeDescTag,
|
||||
Dl: TimeDataSize,
|
||||
Dd: make([]byte, TimeDataSize),
|
||||
Tag: TimeDescTag,
|
||||
Len: TimeDataSize,
|
||||
Data: make([]byte, TimeDataSize),
|
||||
},
|
||||
{
|
||||
Dt: LocationDescTag,
|
||||
Dl: LocationDataSize,
|
||||
Dd: make([]byte, LocationDataSize),
|
||||
Tag: LocationDescTag,
|
||||
Len: LocationDataSize,
|
||||
Data: make([]byte, LocationDataSize),
|
||||
},
|
||||
},
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -301,7 +301,7 @@ func TestAddDescriptorUpdateBigger(t *testing.T) {
|
|||
if err := got.AddDescriptor(TimeDescTag, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a}); err != nil {
|
||||
t.Errorf(errUnexpectedErr, err.Error())
|
||||
}
|
||||
want := AddCrc(pmtTimeBytesResizedBigger)
|
||||
want := AddCRC(pmtTimeBytesResizedBigger)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf(errNotExpectedOut, got, want)
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ func TestAddDescriptorUpdateSmaller(t *testing.T) {
|
|||
if err := got.AddDescriptor(TimeDescTag, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}); err != nil {
|
||||
t.Errorf(errUnexpectedErr, err.Error())
|
||||
}
|
||||
want := AddCrc(pmtTimeBytesResizedSmaller)
|
||||
want := AddCRC(pmtTimeBytesResizedSmaller)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf(errNotExpectedOut, got, want)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ const PacketSize = 184
|
|||
|
||||
// Lengths of section definitions.
|
||||
const (
|
||||
ESSDDefLen = 5
|
||||
ESSDataLen = 5
|
||||
DescDefLen = 2
|
||||
PMTDefLen = 4
|
||||
PATLen = 4
|
||||
|
@ -71,7 +71,7 @@ const (
|
|||
LocationDataSize = 32 // bytes
|
||||
)
|
||||
|
||||
// crc hassh Size
|
||||
// CRC hassh Size
|
||||
const crcSize = 4
|
||||
|
||||
// Consts relating to syntax section.
|
||||
|
@ -100,20 +100,20 @@ const MetadataTag = 0x26
|
|||
// with a program association table (PAT) specific data field.
|
||||
func NewPATPSI() *PSI {
|
||||
return &PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x00,
|
||||
Ssi: true,
|
||||
Pb: false,
|
||||
Sl: 0x0d,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PAT{
|
||||
Pn: 0x01,
|
||||
Pmpid: 0x1000,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x00,
|
||||
SyntaxIndicator: true,
|
||||
PrivateBit: false,
|
||||
SectionLen: 0x0d,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PAT{
|
||||
Program: 0x01,
|
||||
ProgramMapPID: 0x1000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -124,23 +124,23 @@ func NewPATPSI() *PSI {
|
|||
// NOTE: Media PID and stream ID are default to 0.
|
||||
func NewPMTPSI() *PSI {
|
||||
return &PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100,
|
||||
Pil: 0,
|
||||
Essd: &ESSD{
|
||||
St: 0,
|
||||
Epid: 0,
|
||||
Esil: 0x00,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x12,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100,
|
||||
ProgramInfoLen: 0,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0,
|
||||
PID: 0,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -149,30 +149,30 @@ func NewPMTPSI() *PSI {
|
|||
|
||||
// TODO: get rid of these - not a good idea.
|
||||
type (
|
||||
PSIBytes []byte
|
||||
Descriptor []byte
|
||||
PSIBytes []byte
|
||||
DescriptorBytes []byte
|
||||
)
|
||||
|
||||
// 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
|
||||
PointerField byte // Point field
|
||||
PointerFill []byte // Pointer filler bytes
|
||||
TableID byte // Table ID
|
||||
SyntaxIndicator bool // Section syntax indicator (1 for PAT, PMT, CAT)
|
||||
PrivateBit bool // Private bit (0 for PAT, PMT, CAT)
|
||||
SectionLen uint16 // Section length
|
||||
SyntaxSection *SyntaxSection // Table syntax section (length defined by SectionLen) 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
|
||||
type SyntaxSection struct {
|
||||
TableIDExt uint16 // Table ID extension
|
||||
Version byte // Version number
|
||||
CurrentNext bool // Current/next indicator
|
||||
Section byte // Section number
|
||||
LastSection byte // Last section number
|
||||
SpecificData SpecificData // Specific data PAT/PMT
|
||||
}
|
||||
|
||||
// Specific Data, (could be PAT or PMT)
|
||||
|
@ -182,102 +182,102 @@ type SpecificData interface {
|
|||
|
||||
// Program association table, implements SpecificData
|
||||
type PAT struct {
|
||||
Pn uint16 // Program Number
|
||||
Pmpid uint16 // Program map PID
|
||||
Program uint16 // Program Number
|
||||
ProgramMapPID 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
|
||||
ProgramClockPID uint16 // Program clock reference PID.
|
||||
ProgramInfoLen uint16 // Program info length.
|
||||
Descriptors []Descriptor // Number of Program descriptors.
|
||||
StreamSpecificData *StreamSpecificData // 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
|
||||
type StreamSpecificData struct {
|
||||
StreamType byte // Stream type.
|
||||
PID uint16 // Elementary PID.
|
||||
StreamInfoLen uint16 // Elementary stream info length.
|
||||
Descriptors []Descriptor // Elementary stream desriptors
|
||||
}
|
||||
|
||||
// Descriptor
|
||||
type Desc struct {
|
||||
Dt byte // Descriptor tag
|
||||
Dl byte // Descriptor length
|
||||
Dd []byte // Descriptor data
|
||||
type Descriptor struct {
|
||||
Tag byte // Descriptor tag
|
||||
Len byte // Descriptor length
|
||||
Data []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 {
|
||||
out[0] = p.PointerField
|
||||
if p.PointerField != 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)
|
||||
out[1] = p.TableID
|
||||
out[2] = 0x80 | 0x30 | (0x03 & byte(p.SectionLen>>8))
|
||||
out[3] = byte(p.SectionLen)
|
||||
out = append(out, p.SyntaxSection.Bytes()...)
|
||||
out = AddCRC(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the TSS
|
||||
func (t *TSS) Bytes() []byte {
|
||||
// Bytes outputs a byte slice representation of the SyntaxSection
|
||||
func (t *SyntaxSection) 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()...)
|
||||
out[0] = byte(t.TableIDExt >> 8)
|
||||
out[1] = byte(t.TableIDExt)
|
||||
out[2] = 0xc0 | (0x3e & (t.Version << 1)) | (0x01 & asByte(t.CurrentNext))
|
||||
out[3] = t.Section
|
||||
out[4] = t.LastSection
|
||||
out = append(out, t.SpecificData.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.Program >> 8)
|
||||
out[1] = byte(p.Program)
|
||||
out[2] = 0xe0 | (0x1f & byte(p.ProgramMapPID>>8))
|
||||
out[3] = byte(p.ProgramMapPID)
|
||||
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[0] = 0xe0 | (0x1f & byte(p.ProgramClockPID>>8)) // byte 10
|
||||
out[1] = byte(p.ProgramClockPID)
|
||||
out[2] = 0xf0 | (0x03 & byte(p.ProgramInfoLen>>8))
|
||||
out[3] = byte(p.ProgramInfoLen)
|
||||
for _, d := range p.Descriptors {
|
||||
out = append(out, d.Bytes()...)
|
||||
}
|
||||
out = append(out, p.Essd.Bytes()...)
|
||||
out = append(out, p.StreamSpecificData.Bytes()...)
|
||||
return out
|
||||
}
|
||||
|
||||
// Bytes outputs a byte slice representation of the Desc
|
||||
func (d *Desc) Bytes() []byte {
|
||||
func (d *Descriptor) Bytes() []byte {
|
||||
out := make([]byte, DescDefLen)
|
||||
out[0] = d.Dt
|
||||
out[1] = d.Dl
|
||||
out = append(out, d.Dd...)
|
||||
out[0] = d.Tag
|
||||
out[1] = d.Len
|
||||
out = append(out, d.Data...)
|
||||
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 {
|
||||
// Bytes outputs a byte slice representation of the StreamSpecificData
|
||||
func (e *StreamSpecificData) Bytes() []byte {
|
||||
out := make([]byte, ESSDataLen)
|
||||
out[0] = e.StreamType
|
||||
out[1] = 0xe0 | (0x1f & byte(e.PID>>8))
|
||||
out[2] = byte(e.PID)
|
||||
out[3] = 0xf0 | (0x03 & byte(e.StreamInfoLen>>8))
|
||||
out[4] = byte(e.StreamInfoLen)
|
||||
for _, d := range e.Descriptors {
|
||||
out = append(out, d.Bytes()...)
|
||||
}
|
||||
return out
|
||||
|
@ -343,7 +343,7 @@ func (p *PSIBytes) AddDescriptor(tag int, data []byte) error {
|
|||
// If the descriptor of the given tag cannot be found, -1 and a nil slice is returned.
|
||||
//
|
||||
// TODO: check if pmt, return error if not ?
|
||||
func (p *PSIBytes) HasDescriptor(tag int) (int, Descriptor) {
|
||||
func (p *PSIBytes) HasDescriptor(tag int) (int, DescriptorBytes) {
|
||||
descs := p.descriptors()
|
||||
if descs == nil {
|
||||
return -1, nil
|
||||
|
@ -379,7 +379,7 @@ func (p *PSIBytes) createDescriptor(tag int, data []byte) error {
|
|||
(*p)[newDescIdx+1] = byte(dataLen)
|
||||
copy((*p)[newDescIdx+2:newDescIdx+2+dataLen], data)
|
||||
|
||||
// Set length fields and update the psi crc.
|
||||
// Set length fields and update the psi CRC.
|
||||
addedLen := dataLen + 2
|
||||
newProgInfoLen := curProgLen + addedLen
|
||||
p.setProgInfoLen(newProgInfoLen)
|
||||
|
@ -411,7 +411,7 @@ func (p *PSIBytes) descriptors() []byte {
|
|||
}
|
||||
|
||||
// len returns the length of a descriptor in bytes.
|
||||
func (d *Descriptor) len() int {
|
||||
func (d *DescriptorBytes) len() int {
|
||||
return int(2 + (*d)[1])
|
||||
}
|
||||
|
||||
|
|
|
@ -36,43 +36,43 @@ import (
|
|||
var (
|
||||
// standardPat is a minimal PAT.
|
||||
standardPat = PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x00,
|
||||
Ssi: true,
|
||||
Pb: false,
|
||||
Sl: 0x0d,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PAT{
|
||||
Pn: 0x01,
|
||||
Pmpid: 0x1000,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x00,
|
||||
SyntaxIndicator: true,
|
||||
PrivateBit: false,
|
||||
SectionLen: 0x0d,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PAT{
|
||||
Program: 0x01,
|
||||
ProgramMapPID: 0x1000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// standardPmt is a minimal PMT, without time and location descriptors.
|
||||
standardPmt = PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100, // wrong
|
||||
Pil: 0,
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x12,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100, // wrong
|
||||
ProgramInfoLen: 0,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -81,35 +81,35 @@ var (
|
|||
// standardPmtTimeLocation is a standard PMT with time and location
|
||||
// descriptors, but time and location fields zeroed out.
|
||||
standardPmtWithMeta = PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x3e,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100,
|
||||
Pil: PmtTimeLocationPil,
|
||||
Pd: []Desc{
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x3e,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100,
|
||||
ProgramInfoLen: PmtTimeLocationPil,
|
||||
Descriptors: []Descriptor{
|
||||
{
|
||||
Dt: TimeDescTag,
|
||||
Dl: TimeDataSize,
|
||||
Dd: make([]byte, TimeDataSize),
|
||||
Tag: TimeDescTag,
|
||||
Len: TimeDataSize,
|
||||
Data: make([]byte, TimeDataSize),
|
||||
},
|
||||
{
|
||||
Dt: LocationDescTag,
|
||||
Dl: LocationDataSize,
|
||||
Dd: make([]byte, LocationDataSize),
|
||||
Tag: LocationDescTag,
|
||||
Len: LocationDataSize,
|
||||
Data: make([]byte, LocationDataSize),
|
||||
},
|
||||
},
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -206,30 +206,30 @@ var bytesTests = []struct {
|
|||
{
|
||||
name: "pmt to Bytes() with time descriptor",
|
||||
input: PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100, // wrong
|
||||
Pil: 10,
|
||||
Pd: []Desc{
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x12,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100, // wrong
|
||||
ProgramInfoLen: 10,
|
||||
Descriptors: []Descriptor{
|
||||
{
|
||||
Dt: TimeDescTag,
|
||||
Dl: TimeDataSize,
|
||||
Dd: TimeBytes(tstTime1),
|
||||
Tag: TimeDescTag,
|
||||
Len: TimeDataSize,
|
||||
Data: TimeBytes(tstTime1),
|
||||
},
|
||||
},
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -241,35 +241,35 @@ var bytesTests = []struct {
|
|||
{
|
||||
name: "pmt Bytes() with time and location",
|
||||
input: PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &PMT{
|
||||
Pcrpid: 0x0100, // wrong
|
||||
Pil: 10,
|
||||
Pd: []Desc{
|
||||
PointerField: 0x00,
|
||||
TableID: 0x02,
|
||||
SyntaxIndicator: true,
|
||||
SectionLen: 0x12,
|
||||
SyntaxSection: &SyntaxSection{
|
||||
TableIDExt: 0x01,
|
||||
Version: 0,
|
||||
CurrentNext: true,
|
||||
Section: 0,
|
||||
LastSection: 0,
|
||||
SpecificData: &PMT{
|
||||
ProgramClockPID: 0x0100, // wrong
|
||||
ProgramInfoLen: 10,
|
||||
Descriptors: []Descriptor{
|
||||
{
|
||||
Dt: TimeDescTag,
|
||||
Dl: TimeDataSize,
|
||||
Dd: TimeBytes(tstTime2),
|
||||
Tag: TimeDescTag,
|
||||
Len: TimeDataSize,
|
||||
Data: TimeBytes(tstTime2),
|
||||
},
|
||||
{
|
||||
Dt: LocationDescTag,
|
||||
Dl: LocationDataSize,
|
||||
Dd: []byte(locationTstStr1),
|
||||
Tag: LocationDescTag,
|
||||
Len: LocationDataSize,
|
||||
Data: []byte(locationTstStr1),
|
||||
},
|
||||
},
|
||||
Essd: &ESSD{
|
||||
St: 0x1b,
|
||||
Epid: 0x0100,
|
||||
Esil: 0x00,
|
||||
StreamSpecificData: &StreamSpecificData{
|
||||
StreamType: 0x1b,
|
||||
PID: 0x0100,
|
||||
StreamInfoLen: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -283,7 +283,7 @@ var bytesTests = []struct {
|
|||
func TestBytes(t *testing.T) {
|
||||
for _, test := range bytesTests {
|
||||
got := test.input.Bytes()
|
||||
if !bytes.Equal(got, AddCrc(test.want)) {
|
||||
if !bytes.Equal(got, AddCRC(test.want)) {
|
||||
t.Errorf("unexpected error for test %v: got:%v want:%v", test.name, got,
|
||||
test.want)
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ func TestTimestampToBytes(t *testing.T) {
|
|||
func TestTimeUpdate(t *testing.T) {
|
||||
cpy := make([]byte, len(pmtTimeBytes1))
|
||||
copy(cpy, pmtTimeBytes1)
|
||||
cpy = AddCrc(cpy)
|
||||
cpy = AddCRC(cpy)
|
||||
err := UpdateTime(cpy, tstTime2)
|
||||
cpy = cpy[:len(cpy)-4]
|
||||
if err != nil {
|
||||
|
@ -333,7 +333,7 @@ func TestLocationGet(t *testing.T) {
|
|||
func TestLocationUpdate(t *testing.T) {
|
||||
cpy := make([]byte, len(pmtWithMetaTst1))
|
||||
copy(cpy, pmtWithMetaTst1)
|
||||
cpy = AddCrc(cpy)
|
||||
cpy = AddCRC(cpy)
|
||||
err := UpdateLocation(cpy, locationTstStr2)
|
||||
cpy = cpy[:len(cpy)-4]
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue