From 68eec9de988d0e340d377b53dbefbf033fb6d76e Mon Sep 17 00:00:00 2001 From: saxon Date: Tue, 11 Dec 2018 17:05:40 +1030 Subject: [PATCH] psi: wrote func for update timstamp - as well as test (passes). Also wrote func for get timestamp - as well as test (passes) --- stream/mts/psi/psi.go | 36 +++++++++++++--- stream/mts/psi/psi_test.go | 85 ++++++++++++++++++++++++++++++++------ 2 files changed, 102 insertions(+), 19 deletions(-) diff --git a/stream/mts/psi/psi.go b/stream/mts/psi/psi.go index 31360b25..ef3801be 100644 --- a/stream/mts/psi/psi.go +++ b/stream/mts/psi/psi.go @@ -77,7 +77,9 @@ const ( ) const ( - timestampDescTag = 234 + timeDescTag = 234 + descTagIndx = 13 + timeIndx = 15 ) // Program specific information @@ -358,11 +360,33 @@ func TimeToBytes(time uint64) []byte { return s } -// UpdateTimestamp -func UpdateTimestamp(data []byte, t int) error { - psi := ReadPSI(data) - if psi.Tid != PATTableID { - return errors.New("Timestamp update failed because psi is not a PMT") +func chkTime(d []byte) error { + if d[descTagIndx] != timeDescTag { + return errors.New("PSI does not contain a time descriptor, cannot update") } return nil } + +// Updatetime +func UpdateTime(d []byte, t int) error { + err := chkTime(d) + if err != nil { + return err + } + ts := TimeToBytes(uint64(t)) + for i := range d[timeIndx : timeIndx+8] { + d[i+timeIndx] = ts[i] + } + return nil +} + +func GetTime(d []byte) (t uint64, err error) { + err = chkTime(d) + if err != nil { + return 0, err + } + for i := range d[timeIndx : timeIndx+8] { + t |= uint64(d[i+timeIndx]) << uint(56-i*8) + } + return t, nil +} diff --git a/stream/mts/psi/psi_test.go b/stream/mts/psi/psi_test.go index 448b52c2..88408bb1 100644 --- a/stream/mts/psi/psi_test.go +++ b/stream/mts/psi/psi_test.go @@ -6,7 +6,12 @@ import ( ) const ( - testTime = 1235367435 // hex = 49A2360B + tstTime = 1235367435 // hex = 49A2360B + tstTime2 = 1735357535 // hex = 676F745F +) + +const ( + errCmp = "Incorrect output, for: %v wanted: %v, got: %v" ) var ( @@ -54,7 +59,7 @@ var ( }, } // pmt with descriptor in it - StdPmtTimestamp = []byte{ + StdPmtTime = []byte{ 0x00, // pointer // ---- section included in data sent to CRC32 during check @@ -72,7 +77,7 @@ var ( 0xe1, 0x00, // reserved:3|PCR PID:13 0xf0, 0x0a, // reserved:4|unused:2|program info length:10 // Desriptor - byte(timestampDescTag), // Descriptor tag + byte(timeDescTag), // 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. @@ -85,7 +90,7 @@ var ( // 0x15, 0xbd, 0x4d, 0x56, // CRC // ---- } - pmtPsiTimestamped = PSI{ + pmtPsiTime = PSI{ Pf: 0x00, Tid: 0x02, Ssi: true, @@ -101,9 +106,9 @@ var ( Pil: 10, Pd: []Desc{ Desc{ - Dt: byte(timestampDescTag), + Dt: byte(timeDescTag), Dl: byte(8), - Dd: TimeToBytes(testTime), + Dd: TimeToBytes(tstTime), }, }, Essd: &ESSD{ @@ -114,6 +119,38 @@ var ( }, }, } + // pmt with descriptor in it + StdPmtTime2 = []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(timeDescTag), // Descriptor tag + byte(8), // Length of bytes to follow + 0x00, 0x00, 0x00, 0x00, 0x67, 0x6F, 0x74, 0x5F, // 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 + // ---- + } ) // Test Bytes for a standard pat @@ -122,7 +159,7 @@ func TestBytesPAT1(t *testing.T) { // Remove crc32 got = got[:len(got)-4] if !bytes.Equal(StdPat, got) { - t.Errorf("Incorrect output, wanted: %v, got: %v", StdPat, got) + t.Errorf(errCmp, "TestBytesPAT1", StdPat, got) } } @@ -132,24 +169,46 @@ func TestBytesPMT1(t *testing.T) { // Remove crc32 got = got[:len(got)-4] if !bytes.Equal(StdPmt, got) { - t.Errorf("Incorrect output, wanted: %v, got: %v", StdPmt, got) + t.Errorf(errCmp, "TestBytesPMT1", StdPmt, got) } } // A quick sanity check of the int64 time to []byte func func TestTimestampToBytes(t *testing.T) { - timeBytes := TimeToBytes(testTime) + timeBytes := TimeToBytes(tstTime) if !bytes.Equal(timeSlice, timeBytes) { - t.Errorf("Incorrect results, wanted: %v, got: %v", timeSlice, timeBytes) + t.Errorf(errCmp, "testTimeStampToBytes", timeSlice, timeBytes) } } // Test Bytes for a a standard PMT with a descripot containing a timestamp func TestBytesPmt2(t *testing.T) { - got := pmtPsiTimestamped.Bytes() + got := pmtPsiTime.Bytes() // Remove crc32 got = got[:len(got)-4] - if !bytes.Equal(StdPmtTimestamp, got) { - t.Errorf("Incorrect output, wanted: %v, got: %v", StdPmtTimestamp, got) + if !bytes.Equal(StdPmtTime, got) { + t.Errorf(errCmp, "testBytesPmt2", StdPmtTime, got) + } +} + +func TestTimeUpdate(t *testing.T) { + cpy := make([]byte, len(StdPmtTime)) + copy(cpy, StdPmtTime) + err := UpdateTime(cpy, tstTime2) + if err != nil { + t.Errorf("Update time returned err: %v", err) + } + if !bytes.Equal(StdPmtTime2, cpy) { + t.Errorf(errCmp, "TestTimeUpdate", StdPmtTime2, cpy) + } +} + +func TestTimeGet(t *testing.T) { + s, err := GetTime(StdPmtTime) + if err != nil { + t.Errorf("Getting timestamp failed with err: %v", err) + } + if s != tstTime { + t.Errorf(errCmp, "TestTimeGet", tstTime, s) } }