From b036517329a093908bec8a29272600095f3389ed Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Sun, 19 Aug 2018 09:59:33 +0930 Subject: [PATCH] generator: add CRC32 calculation This uses a big-endian CRC32 algorithm rather than the hash/crc32 package's little-endian implementation. --- generator/mpegts_generator.go | 59 ++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/generator/mpegts_generator.go b/generator/mpegts_generator.go index 42dceaa1..a3c6712c 100644 --- a/generator/mpegts_generator.go +++ b/generator/mpegts_generator.go @@ -29,6 +29,9 @@ LICENSE package generator import ( + "encoding/binary" + "hash/crc32" + "math/bits" "time" "bitbucket.org/ausocean/av/mpegts" @@ -42,6 +45,7 @@ var ( patTable = []byte{ 0x00, // pointer + // ---- section included in data sent to CRC32 during check // table header 0x00, // table id 0xb0, // section syntax indicator:1|private bit:1|reserved:2|section length:2|more bytes...:2 @@ -56,13 +60,15 @@ var ( 0x00, 0x01, // Program number 0xf0, 0x00, // reserved:3|program map PID:13 - 0x2a, 0xb1, 0x04, 0xb2, // CRC + // 0x2a, 0xb1, 0x04, 0xb2, // CRC + // ---- } pmtTable = []byte{ 0x00, // pointer + // ---- section included in data sent to CRC32 during check // table header - 0x02, // table id. + 0x02, // table id 0xb0, // section syntax indicator:1|private bit:1|reserved:2|section length:2|more bytes...:2 0x12, // more bytes... @@ -79,19 +85,56 @@ var ( 0x1b, // stream type 0xe1, 0x00, // reserved:3|elementary PID:13 0xf0, 0x00, // reserved:4|unused:2|ES info length:10 - // No elementary stream descriptos since ES info length is 0. + // No elementary stream descriptors since ES info length is 0. - 0x15, 0xbd, 0x4d, 0x56, // CRC + // 0x15, 0xbd, 0x4d, 0x56, // CRC + // ---- } ) func init() { - for len(patTable) < psiPacketSize { - patTable = append(patTable, 0xff) + // Generate IEEE polynomial table + // for the big-endian algorithm. + crcTable := crc32_MakeTable(bits.Reverse32(crc32.IEEE)) + + patTable = completePSI(patTable, crcTable) + pmtTable = completePSI(pmtTable, crcTable) +} + +func completePSI(psi []byte, tab *crc32.Table) []byte { + var buf [4]byte + crc := crc32_Update(0xffffffff, tab, psi[1:]) + binary.BigEndian.PutUint32(buf[:], crc) + dst := make([]byte, len(psi), psiPacketSize) + copy(dst, psi) + dst = append(dst, buf[:]...) + for len(dst) < cap(dst) { + dst = append(dst, 0xff) } - for len(pmtTable) < psiPacketSize { - pmtTable = append(pmtTable, 0xff) + return dst +} + +func crc32_MakeTable(poly uint32) *crc32.Table { + var t crc32.Table + for i := range t { + crc := uint32(i) << 24 + for j := 0; j < 8; j++ { + if crc&0x80000000 != 0 { + crc = (crc << 1) ^ poly + } else { + crc <<= 1 + } + } + t[i] = crc } + return &t +} + +func crc32_Update(crc uint32, tab *crc32.Table, p []byte) uint32 { + for _, v := range p { + crc = tab[byte(crc>>24)^v] ^ (crc << 8) + } + return crc } const (