diff --git a/stream/mts/psi/psi.go b/stream/mts/psi/psi.go index 6a88fc50..31360b25 100644 --- a/stream/mts/psi/psi.go +++ b/stream/mts/psi/psi.go @@ -1,6 +1,7 @@ package psi import ( + "encoding/binary" "errors" "hash/crc32" "math/bits" @@ -280,7 +281,7 @@ func (p *PAT) Bytes() []byte { // 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[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) @@ -351,6 +352,12 @@ func crc32_Update(crc uint32, tab *crc32.Table, p []byte) uint32 { return crc } +func TimeToBytes(time uint64) []byte { + s := make([]byte, 8) + binary.BigEndian.PutUint64(s, time) + return s +} + // UpdateTimestamp func UpdateTimestamp(data []byte, t int) error { psi := ReadPSI(data) diff --git a/stream/mts/psi/psi_test.go b/stream/mts/psi/psi_test.go index 4d09dd6c..448b52c2 100644 --- a/stream/mts/psi/psi_test.go +++ b/stream/mts/psi/psi_test.go @@ -5,8 +5,15 @@ import ( "testing" ) +const ( + testTime = 1235367435 // hex = 49A2360B +) + var ( - patPsi = PSI{ + timeSlice = []byte{ + 0x00, 0x00, 0x00, 0x00, 0x49, 0xA2, 0x36, 0x0B, + } + patPsi1 = PSI{ Pf: 0x00, Tid: 0x00, Ssi: true, @@ -24,7 +31,7 @@ var ( }, }, } - pmtPsi = PSI{ + pmtPsi1 = PSI{ Pf: 0x00, Tid: 0x02, Ssi: true, @@ -36,7 +43,7 @@ var ( Sn: 0, Lsn: 0, Sd: &PMT{ - Pcrpid: 0x1100, // wrong + Pcrpid: 0x0100, // wrong Pil: 0, Essd: &ESSD{ St: 0x1b, @@ -46,22 +53,103 @@ var ( }, }, } + // pmt with descriptor in it + StdPmtTimestamp = []byte{ + 0x00, // pointer + + // ---- section included in data sent to CRC32 during check + // table header + 0x02, // table id + 0xb0, // section syntax indicator:1|private bit:1|reserved:2|section length:2|more bytes...:2 + 0x12, // more bytes... + + // syntax section + 0x00, 0x01, // table id extension + 0xc1, // reserved bits:3|version:5|use now:1 + 0x00, // section number + 0x00, // last section number + // table data + 0xe1, 0x00, // reserved:3|PCR PID:13 + 0xf0, 0x0a, // reserved:4|unused:2|program info length:10 + // Desriptor + byte(timestampDescTag), // Descriptor tag + byte(8), // Length of bytes to follow + 0x00, 0x00, 0x00, 0x00, 0x49, 0xA2, 0x36, 0x0B, // timestamp + // No program descriptors since program info length is 0. + // elementary stream info data + 0x1b, // stream type + 0xe1, 0x00, // reserved:3|elementary PID:13 + 0xf0, 0x00, // reserved:4|unused:2|ES info length:10 + // No elementary stream descriptors since ES info length is 0. + + // 0x15, 0xbd, 0x4d, 0x56, // CRC + // ---- + } + pmtPsiTimestamped = PSI{ + Pf: 0x00, + Tid: 0x02, + Ssi: true, + Sl: uint16(0x12), + Tss: &TSS{ + Tide: uint16(0x01), + V: 0, + Cni: true, + Sn: 0, + Lsn: 0, + Sd: &PMT{ + Pcrpid: 0x0100, // wrong + Pil: 10, + Pd: []Desc{ + Desc{ + Dt: byte(timestampDescTag), + Dl: byte(8), + Dd: TimeToBytes(testTime), + }, + }, + Essd: &ESSD{ + St: 0x1b, + Epid: 0x0100, + Esil: 0x00, + }, + }, + }, + } ) -func TestWritePAT1(t *testing.T) { - got := patPsi.Bytes() +// Test Bytes for a standard pat +func TestBytesPAT1(t *testing.T) { + got := patPsi1.Bytes() // Remove crc32 got = got[:len(got)-4] - if !bytes.Equal(StdPat, got[:len(got)-4]) { + if !bytes.Equal(StdPat, got) { t.Errorf("Incorrect output, wanted: %v, got: %v", StdPat, got) } } -func TestWritePMT1(t *testing.T) { - got := pmtPsi.Bytes() +// Test Bytes for a standard pmt +func TestBytesPMT1(t *testing.T) { + got := pmtPsi1.Bytes() // Remove crc32 got = got[:len(got)-4] - if !bytes.Equal(StdPmt, got[:len(got)-4]) { + if !bytes.Equal(StdPmt, got) { t.Errorf("Incorrect output, wanted: %v, got: %v", StdPmt, got) } } + +// A quick sanity check of the int64 time to []byte func +func TestTimestampToBytes(t *testing.T) { + timeBytes := TimeToBytes(testTime) + if !bytes.Equal(timeSlice, timeBytes) { + t.Errorf("Incorrect results, wanted: %v, got: %v", timeSlice, timeBytes) + } +} + +// Test Bytes for a a standard PMT with a descripot containing a timestamp +func TestBytesPmt2(t *testing.T) { + got := pmtPsiTimestamped.Bytes() + // Remove crc32 + got = got[:len(got)-4] + if !bytes.Equal(StdPmtTimestamp, got) { + t.Errorf("Incorrect output, wanted: %v, got: %v", StdPmtTimestamp, got) + } +}