diff --git a/container/mts/encoder.go b/container/mts/encoder.go index 95b99a22..330d52d1 100644 --- a/container/mts/encoder.go +++ b/container/mts/encoder.go @@ -106,44 +106,6 @@ const ( defaultMediaPID = PIDVideo ) -// Some common manifestations of PSI. -var ( - // StandardPAT is a minimal PAT. - StandardPAT = 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: 0x1000, - }, - }, - } - - // Base PMT is a minimal PMT without specific data. - BasePMT = psi.PSI{ - Pf: 0x00, - Tid: 0x02, - Ssi: true, - Sl: 0x12, - Tss: &psi.TSS{ - Tide: 0x01, - V: 0, - Cni: true, - Sn: 0, - Lsn: 0, - }, - } -) - // Meta allows addition of metadata to encoded mts from outside of this pkg. // See meta pkg for usage. // @@ -153,11 +115,6 @@ var Meta *meta.Data // This will help us obtain a realtime for timestamp meta encoding. var RealTime = realtime.NewRealTime() -var ( - patTable = StandardPAT.Bytes() - pmtTable []byte -) - type logger interface { Debug(string, ...interface{}) Info(string, ...interface{}) @@ -188,6 +145,9 @@ type Encoder struct { mediaPID uint16 streamID byte + pmt *psi.PSI + patBytes, pmtBytes []byte + // log is a function that will be used through the encoder code for logging. log logger } @@ -205,6 +165,8 @@ func NewEncoder(dst io.WriteCloser, log logger, options ...func(*Encoder) error) streamID: defaultStreamID, continuity: map[uint16]byte{PatPid: 0, PmtPid: 0, defaultMediaPID: 0}, log: log, + patBytes: psi.NewPATPSI().Bytes(), + pmt: psi.NewPMTPSI(), } for _, option := range options { @@ -215,17 +177,9 @@ func NewEncoder(dst io.WriteCloser, log logger, options ...func(*Encoder) error) } log.Debug("encoder options applied") - pmt := BasePMT - pmt.Tss.Sd = &psi.PMT{ - Pcrpid: 0x0100, - Pil: 0, - Essd: &psi.ESSD{ - St: byte(e.streamID), - Epid: e.mediaPID, - Esil: 0x00, - }, - } - pmtTable = pmt.Bytes() + e.pmt.Tss.Sd.(*psi.PMT).Essd.St = e.streamID + e.pmt.Tss.Sd.(*psi.PMT).Essd.Epid = e.mediaPID + e.pmtBytes = e.pmt.Bytes() return e, nil } @@ -324,7 +278,7 @@ func (e *Encoder) writePSI() error { PID: PatPid, CC: e.ccFor(PatPid), AFC: hasPayload, - Payload: psi.AddPadding(patTable), + Payload: psi.AddPadding(e.patBytes), } _, err := e.dst.Write(patPkt.Bytes(e.tsSpace[:PacketSize])) if err != nil { @@ -332,7 +286,7 @@ func (e *Encoder) writePSI() error { } e.pktCount++ - pmtTable, err = updateMeta(pmtTable, e.log) + e.pmtBytes, err = updateMeta(e.pmtBytes, e.log) if err != nil { return err @@ -344,7 +298,7 @@ func (e *Encoder) writePSI() error { PID: PmtPid, CC: e.ccFor(PmtPid), AFC: hasPayload, - Payload: psi.AddPadding(pmtTable), + Payload: psi.AddPadding(e.pmtBytes), } _, err = e.dst.Write(pmtPkt.Bytes(e.tsSpace[:PacketSize])) if err != nil { diff --git a/container/mts/mpegts_test.go b/container/mts/mpegts_test.go index 688d9135..ec82adfb 100644 --- a/container/mts/mpegts_test.go +++ b/container/mts/mpegts_test.go @@ -98,13 +98,15 @@ func TestGetPTSRange1(t *testing.T) { // writePSI is a helper function write the PSI found at the start of a clip. func writePSI(b *bytes.Buffer) error { + patBytes := psi.NewPATPSI().Bytes() + pmtBytes := psi.NewPMTPSI().Bytes() // Write PAT. pat := Packet{ PUSI: true, PID: PatPid, CC: 0, AFC: HasPayload, - Payload: psi.AddPadding(patTable), + Payload: psi.AddPadding(patBytes), } _, err := b.Write(pat.Bytes(nil)) if err != nil { @@ -117,7 +119,7 @@ func writePSI(b *bytes.Buffer) error { PID: PmtPid, CC: 0, AFC: HasPayload, - Payload: psi.AddPadding(pmtTable), + Payload: psi.AddPadding(pmtBytes), } _, err = b.Write(pmt.Bytes(nil)) if err != nil { diff --git a/container/mts/payload_test.go b/container/mts/payload_test.go index 35259fe4..d3974a99 100644 --- a/container/mts/payload_test.go +++ b/container/mts/payload_test.go @@ -137,13 +137,15 @@ func TestExtract(t *testing.T) { // writePSIWithMeta writes PSI to b with updated metadata. func writePSIWithMeta(b *bytes.Buffer, t *testing.T) error { + patBytes := psi.NewPATPSI().Bytes() + pmtBytes := psi.NewPMTPSI().Bytes() // Write PAT. pat := Packet{ PUSI: true, PID: PatPid, CC: 0, AFC: HasPayload, - Payload: psi.AddPadding(patTable), + Payload: psi.AddPadding(patBytes), } _, err := b.Write(pat.Bytes(nil)) if err != nil { @@ -151,7 +153,7 @@ func writePSIWithMeta(b *bytes.Buffer, t *testing.T) error { } // Update the meta in the pmt table. - pmtTable, err = updateMeta(pmtTable, (*testLogger)(t)) + pmtBytes, err = updateMeta(pmtBytes, (*testLogger)(t)) if err != nil { return err } @@ -162,7 +164,7 @@ func writePSIWithMeta(b *bytes.Buffer, t *testing.T) error { PID: PmtPid, CC: 0, AFC: HasPayload, - Payload: psi.AddPadding(pmtTable), + Payload: psi.AddPadding(pmtBytes), } _, err = b.Write(pmt.Bytes(nil)) if err != nil { diff --git a/container/mts/psi/psi.go b/container/mts/psi/psi.go index 96b630b1..f1771803 100644 --- a/container/mts/psi/psi.go +++ b/container/mts/psi/psi.go @@ -96,6 +96,57 @@ const DescriptorsIdx = ProgramInfoLenIdx2 + 1 // MetadataTag is the descriptor tag used for metadata. const MetadataTag = 0x26 +// NewPATPSI will provide a standard program specific information (PSI) table +// 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, + }, + }, + } +} + +// NewPMTPSI will provide a standard program specific information (PSI) table +// with a program mapping table specific data field. +// 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, + }, + }, + }, + } +} + // TODO: get rid of these - not a good idea. type ( PSIBytes []byte