mirror of https://bitbucket.org/ausocean/av.git
psi: restructured psi_test.go and started writing tests for gps
This commit is contained in:
parent
14e5676f6f
commit
3cf6c00991
|
@ -32,14 +32,14 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TimeToBytes(time uint64) []byte {
|
func TimeBytes(time uint64) (s []byte) {
|
||||||
s := make([]byte, 8)
|
s = make([]byte, timeSize)
|
||||||
binary.BigEndian.PutUint64(s, time)
|
binary.BigEndian.PutUint64(s[:], time)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func chkTime(d []byte) error {
|
func chkTime(d []byte) error {
|
||||||
if d[descTagIndx] != timeDescTag {
|
if d[timeTagIndx] != timeDescTag {
|
||||||
return errors.New("PSI does not contain a time descriptor, cannot update")
|
return errors.New("PSI does not contain a time descriptor, cannot update")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -51,7 +51,7 @@ func UpdateTime(d []byte, t int) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ts := TimeToBytes(uint64(t))
|
ts := TimeBytes(uint64(t))
|
||||||
for i := range d[timeIndx : timeIndx+8] {
|
for i := range d[timeIndx : timeIndx+8] {
|
||||||
d[i+timeIndx] = ts[i]
|
d[i+timeIndx] = ts[i]
|
||||||
}
|
}
|
||||||
|
@ -68,3 +68,9 @@ func TimeOf(d []byte) (t uint64, err error) {
|
||||||
}
|
}
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GpsStrBytes(l string) (out []byte) {
|
||||||
|
out = make([]byte, gpsSize)
|
||||||
|
copy(out, []byte(l))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -50,8 +50,17 @@ const (
|
||||||
// Consts relating to time description
|
// Consts relating to time description
|
||||||
const (
|
const (
|
||||||
timeDescTag = 234
|
timeDescTag = 234
|
||||||
descTagIndx = 13
|
timeTagIndx = 13
|
||||||
timeIndx = 15
|
timeIndx = 15
|
||||||
|
timeSize = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
// Consts relating to gps description
|
||||||
|
const (
|
||||||
|
gpsDescTag = 235
|
||||||
|
gpsTagIndx = 23
|
||||||
|
gpsIndx = 25
|
||||||
|
gpsSize = 32 // bytes
|
||||||
)
|
)
|
||||||
|
|
||||||
// Program specific information
|
// Program specific information
|
||||||
|
|
|
@ -31,94 +31,95 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Times as ints for testing
|
||||||
const (
|
const (
|
||||||
tstTime = 1235367435 // 0x49A2360B
|
tstTime1 = 1235367435 // 0x49A2360B
|
||||||
tstTime2 = 1735357535 // 0x676F745F
|
tstTime2 = 1735357535 // 0x676F745F
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GPS string for testing
|
||||||
|
const (
|
||||||
|
gpsTstStr1 = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"
|
||||||
|
gpsTstStr2 = "$GPGGA,183710,4902.048,N,02171.020,E,1,09,0.5,547.2,M,43.4,M,,*42"
|
||||||
|
)
|
||||||
|
|
||||||
|
// err message
|
||||||
const (
|
const (
|
||||||
errCmp = "Incorrect output, for: %v wanted: %v, got: %v"
|
errCmp = "Incorrect output, for: %v wanted: %v, got: %v"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Frist write tests
|
// Test time to bytes test Data
|
||||||
|
|
||||||
var (
|
var (
|
||||||
timeSlice = []byte{
|
timeSlice = []byte{
|
||||||
0x00, 0x00, 0x00, 0x00, 0x49, 0xA2, 0x36, 0x0B,
|
0x00, 0x00, 0x00, 0x00, 0x49, 0xA2, 0x36, 0x0B,
|
||||||
}
|
}
|
||||||
patPsi1 = PSI{
|
)
|
||||||
Pf: 0x00,
|
|
||||||
Tid: 0x00,
|
|
||||||
Ssi: true,
|
|
||||||
Pb: false,
|
|
||||||
Sl: uint16(0x0d),
|
|
||||||
Tss: &TSS{
|
|
||||||
Tide: uint16(0x01),
|
|
||||||
V: 0,
|
|
||||||
Cni: true,
|
|
||||||
Sn: 0,
|
|
||||||
Lsn: 0,
|
|
||||||
Sd: &PAT{
|
|
||||||
Pn: uint16(0x01),
|
|
||||||
Pmpid: uint16(0x1000),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
pmtPsi1 = 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: 0,
|
|
||||||
Essd: &ESSD{
|
|
||||||
St: 0x1b,
|
|
||||||
Epid: 0x0100,
|
|
||||||
Esil: 0x00,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// pmt with descriptor in it
|
|
||||||
StdPmtTime = []byte{
|
|
||||||
0x00, // pointer
|
|
||||||
|
|
||||||
// ---- section included in data sent to CRC32 during check
|
// Parts to construct bytes of pmt with time and bytes
|
||||||
// table header
|
var (
|
||||||
0x02, // table id
|
pmtTimeGpsBytesPart1 = []byte{
|
||||||
0xb0, // section syntax indicator:1|private bit:1|reserved:2|section length:2|more bytes...:2
|
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00, 0x00, 0xe1, 0x00, 0xf0, 0x0a,
|
||||||
0x12, // more bytes...
|
byte(timeDescTag), // Descriptor tag for timestamp
|
||||||
|
byte(timeSize), // Length of bytes to follow
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x67, 0x6F, 0x74, 0x5F, // Timestamp data
|
||||||
|
byte(gpsDescTag), // Descriptor tag for gps
|
||||||
|
byte(gpsSize), // Length of bytes to follow
|
||||||
|
}
|
||||||
|
pmtTimeGpsBytesPart2 = []byte{
|
||||||
|
0x1b, 0xe1, 0x00, 0xf0, 0x00,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// syntax section
|
var (
|
||||||
0x00, 0x01, // table id extension
|
// Bytes representing pmt with tstTime1
|
||||||
0xc1, // reserved bits:3|version:5|use now:1
|
pmtTimeBytes1 = []byte{
|
||||||
0x00, // section number
|
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00, 0x00, 0xe1, 0x00, 0xf0, 0x0a,
|
||||||
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(timeDescTag), // Descriptor tag
|
||||||
byte(8), // Length of bytes to follow
|
byte(timeSize), // Length of bytes to follow
|
||||||
0x00, 0x00, 0x00, 0x00, 0x49, 0xA2, 0x36, 0x0B, // timestamp
|
0x00, 0x00, 0x00, 0x00, 0x49, 0xA2, 0x36, 0x0B, // timestamp
|
||||||
// No program descriptors since program info length is 0.
|
0x1b, 0xe1, 0x00, 0xf0, 0x00,
|
||||||
// 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
|
|
||||||
// ----
|
|
||||||
}
|
}
|
||||||
pmtPsiTime = PSI{
|
|
||||||
|
// Bytes representing pmt with tstTime 2
|
||||||
|
pmtTimeBytes2 = []byte{
|
||||||
|
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00, 0x00, 0xe1, 0x00, 0xf0, 0x0a,
|
||||||
|
byte(timeDescTag), // Descriptor tag
|
||||||
|
byte(timeSize), // Length of bytes to follow
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x67, 0x6F, 0x74, 0x5F, // timestamp
|
||||||
|
0x1b, 0xe1, 0x00, 0xf0, 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes representing pmt with time1 and gps1
|
||||||
|
pmtTimeGpsBytes1 = buildPmtTimeGpsBytes(gpsTstStr1)
|
||||||
|
|
||||||
|
// bytes representing pmt with with time1 and gps 2
|
||||||
|
pmtTimeGpsBytes2 = buildPmtTimeGpsBytes(gpsTstStr2)
|
||||||
|
)
|
||||||
|
|
||||||
|
// bytesTests contains data for testing the Bytes() funcs for the PSI data struct
|
||||||
|
var bytesTests = []struct {
|
||||||
|
name string
|
||||||
|
input PSI
|
||||||
|
want []byte
|
||||||
|
}{
|
||||||
|
// Pat test
|
||||||
|
{
|
||||||
|
name: "pat Bytes()",
|
||||||
|
input: stdPat,
|
||||||
|
want: stdPatBytes,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Pmt test data no descriptor
|
||||||
|
{
|
||||||
|
name: "pmt to Bytes() without descriptors",
|
||||||
|
input: stdPmt,
|
||||||
|
want: stdPmtBytes,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Pmt with time descriptor
|
||||||
|
{
|
||||||
|
name: "pmt to Bytes() with time descriptor",
|
||||||
|
input: PSI{
|
||||||
Pf: 0x00,
|
Pf: 0x00,
|
||||||
Tid: 0x02,
|
Tid: 0x02,
|
||||||
Ssi: true,
|
Ssi: true,
|
||||||
|
@ -135,8 +136,8 @@ var (
|
||||||
Pd: []Desc{
|
Pd: []Desc{
|
||||||
Desc{
|
Desc{
|
||||||
Dt: byte(timeDescTag),
|
Dt: byte(timeDescTag),
|
||||||
Dl: byte(8),
|
Dl: byte(timeSize),
|
||||||
Dd: TimeToBytes(tstTime),
|
Dd: TimeBytes(tstTime1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Essd: &ESSD{
|
Essd: &ESSD{
|
||||||
|
@ -146,97 +147,108 @@ var (
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
want: pmtTimeBytes1,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Pmt with time and gps
|
||||||
|
{
|
||||||
|
name: "pmt Bytes() with time and gps",
|
||||||
|
input: 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(timeDescTag),
|
||||||
|
Dl: byte(timeSize),
|
||||||
|
Dd: TimeBytes(tstTime2),
|
||||||
|
},
|
||||||
|
Desc{
|
||||||
|
Dt: byte(gpsDescTag),
|
||||||
|
Dl: byte(gpsSize),
|
||||||
|
Dd: GpsStrBytes(gpsTstStr1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Essd: &ESSD{
|
||||||
|
St: 0x1b,
|
||||||
|
Epid: 0x0100,
|
||||||
|
Esil: 0x00,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: buildPmtTimeGpsBytes(gpsTstStr1),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// pmt with descriptor in it
|
|
||||||
StdPmtTime2 = []byte{
|
|
||||||
0x00, // pointer
|
|
||||||
|
|
||||||
// ---- section included in data sent to CRC32 during check
|
// TestBytes ensures that the Bytes() funcs are working correctly to take PSI
|
||||||
// table header
|
// structs and converting them to byte slices
|
||||||
0x02, // table id
|
func TestBytes(t *testing.T) {
|
||||||
0xb0, // section syntax indicator:1|private bit:1|reserved:2|section length:2|more bytes...:2
|
for _, test := range bytesTests {
|
||||||
0x12, // more bytes...
|
got := test.input.Bytes()
|
||||||
|
// Remove crc32s
|
||||||
// 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
|
|
||||||
func TestBytesPAT1(t *testing.T) {
|
|
||||||
got := patPsi1.Bytes()
|
|
||||||
// Remove crc32
|
|
||||||
got = got[:len(got)-4]
|
got = got[:len(got)-4]
|
||||||
if !bytes.Equal(StdPat, got) {
|
if !bytes.Equal(got, test.want) {
|
||||||
t.Errorf(errCmp, "TestBytesPAT1", StdPat, got)
|
t.Errorf("unexpected error for test %v: got:%v want:%v", test.name, got,
|
||||||
|
test.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
|
||||||
t.Errorf(errCmp, "TestBytesPMT1", StdPmt, got)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A quick sanity check of the int64 time to []byte func
|
// A quick sanity check of the int64 time to []byte func
|
||||||
func TestTimestampToBytes(t *testing.T) {
|
func TestTimestampToBytes(t *testing.T) {
|
||||||
timeBytes := TimeToBytes(tstTime)
|
tb := TimeBytes(tstTime1)
|
||||||
if !bytes.Equal(timeSlice, timeBytes) {
|
if !bytes.Equal(timeSlice, tb) {
|
||||||
t.Errorf(errCmp, "testTimeStampToBytes", timeSlice, timeBytes)
|
t.Errorf(errCmp, "testTimeStampToBytes", timeSlice, tb)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test Bytes for a a standard PMT with a descripot containing a timestamp
|
|
||||||
func TestBytesPmt2(t *testing.T) {
|
|
||||||
got := pmtPsiTime.Bytes()
|
|
||||||
// Remove crc32
|
|
||||||
got = got[:len(got)-4]
|
|
||||||
if !bytes.Equal(StdPmtTime, got) {
|
|
||||||
t.Errorf(errCmp, "testBytesPmt2", StdPmtTime, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeUpdate(t *testing.T) {
|
func TestTimeUpdate(t *testing.T) {
|
||||||
cpy := make([]byte, len(StdPmtTime))
|
cpy := make([]byte, len(pmtTimeBytes1))
|
||||||
copy(cpy, StdPmtTime)
|
copy(cpy, pmtTimeBytes1)
|
||||||
err := UpdateTime(cpy, tstTime2)
|
err := UpdateTime(cpy, tstTime2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Update time returned err: %v", err)
|
t.Errorf("Update time returned err: %v", err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(StdPmtTime2, cpy) {
|
if !bytes.Equal(pmtTimeBytes2, cpy) {
|
||||||
t.Errorf(errCmp, "TestTimeUpdate", StdPmtTime2, cpy)
|
t.Errorf(errCmp, "TestTimeUpdate", pmtTimeBytes2, cpy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeGet(t *testing.T) {
|
func TestTimeGet(t *testing.T) {
|
||||||
s, err := TimeOf(StdPmtTime)
|
s, err := TimeOf(pmtTimeBytes1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Getting timestamp failed with err: %v", err)
|
t.Errorf("Getting timestamp failed with err: %v", err)
|
||||||
}
|
}
|
||||||
if s != tstTime {
|
if s != tstTime1 {
|
||||||
t.Errorf(errCmp, "TestTimeGet", tstTime, s)
|
t.Errorf(errCmp, "TestTimeGet", tstTime1, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGpsUpdate(t *testing.T) {
|
||||||
|
cpy := make([]byte, len(pmtTimeGpsBytes1))
|
||||||
|
copy(cpy, pmtTimeGpsBytes1)
|
||||||
|
err := UpdateGps(cpy, tstTime2)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Update time returned err: %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(pmtTimeGpsBytes2, cpy) {
|
||||||
|
t.Errorf(errCmp, "TestGpsUpdate", pmtTimeGpsBytes2, cpy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPmtTimeGpsBytes(tstStr string) []byte {
|
||||||
|
return append(append(append(make([]byte, 0), pmtTimeGpsBytesPart1...),
|
||||||
|
GpsStrBytes(tstStr)...), pmtTimeGpsBytesPart2...)
|
||||||
|
}
|
||||||
|
|
|
@ -26,10 +26,54 @@ LICENSE
|
||||||
|
|
||||||
package psi
|
package psi
|
||||||
|
|
||||||
// TODO: Finish off mts/psi so that we can create pat and pmt tables instead
|
// Std PSI in struct form without descriptor
|
||||||
// of hardcoding.
|
|
||||||
var (
|
var (
|
||||||
StdPat = []byte{
|
stdPat = PSI{
|
||||||
|
Pf: 0x00,
|
||||||
|
Tid: 0x00,
|
||||||
|
Ssi: true,
|
||||||
|
Pb: false,
|
||||||
|
Sl: uint16(0x0d),
|
||||||
|
Tss: &TSS{
|
||||||
|
Tide: uint16(0x01),
|
||||||
|
V: 0,
|
||||||
|
Cni: true,
|
||||||
|
Sn: 0,
|
||||||
|
Lsn: 0,
|
||||||
|
Sd: &PAT{
|
||||||
|
Pn: uint16(0x01),
|
||||||
|
Pmpid: uint16(0x1000),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
stdPmt = 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: 0,
|
||||||
|
Essd: &ESSD{
|
||||||
|
St: 0x1b,
|
||||||
|
Epid: 0x0100,
|
||||||
|
Esil: 0x00,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Std PSI in bytes form
|
||||||
|
var (
|
||||||
|
stdPatBytes = []byte{
|
||||||
0x00, // pointer
|
0x00, // pointer
|
||||||
|
|
||||||
// ---- section included in data sent to CRC32 during check
|
// ---- section included in data sent to CRC32 during check
|
||||||
|
@ -50,7 +94,7 @@ var (
|
||||||
// 0x2a, 0xb1, 0x04, 0xb2, // CRC
|
// 0x2a, 0xb1, 0x04, 0xb2, // CRC
|
||||||
// ----
|
// ----
|
||||||
}
|
}
|
||||||
StdPmt = []byte{
|
stdPmtBytes = []byte{
|
||||||
0x00, // pointer
|
0x00, // pointer
|
||||||
|
|
||||||
// ---- section included in data sent to CRC32 during check
|
// ---- section included in data sent to CRC32 during check
|
||||||
|
|
Loading…
Reference in New Issue