diff --git a/example/test.go b/example/test.go index 7666aed..b279abc 100644 --- a/example/test.go +++ b/example/test.go @@ -16,9 +16,25 @@ type Stream struct { Title string Data bytes.Buffer Type uint + PTS uint + PCR uint } -func main() { +type Sample struct { + Type uint + PCR uint64 + PTS uint64 + DTS uint64 + Data []byte +} + +func readSamples(ch chan Sample) { + defer func() { + close(ch) + }() + + debug := false + var file *os.File var err error if file, err = os.Open("/tmp/out.ts"); err != nil { @@ -66,8 +82,14 @@ func main() { return } if stream.Data.Len() == int(stream.Header.DataLength) { - fmt.Println(stream.Type, stream.Title, stream.Data.Len(), "total") - fmt.Println(hex.Dump(stream.Data.Bytes())) + if debug { + fmt.Println(stream.Type, stream.Title, stream.Data.Len(), "total") + fmt.Println(hex.Dump(stream.Data.Bytes())) + } + ch <- Sample{ + Type: stream.Type, + Data: stream.Data.Bytes(), + } } return } @@ -76,7 +98,9 @@ func main() { if header, n, err = ts.ReadTSPacket(file, data[:]); err != nil { return } - fmt.Println(header, n) + if debug { + fmt.Println(header, n) + } payload = data[:n] pr := bytes.NewReader(payload) @@ -94,7 +118,7 @@ func main() { return } //fmt.Println("pmt", pmt) - if true { + if debug { fmt.Println(hex.Dump(payload)) } } @@ -109,3 +133,18 @@ func main() { } } +func main() { + ch := make(chan Sample) + go readSamples(ch) + + for { + var sample Sample + var ok bool + if sample, ok = <-ch; !ok { + break + } + if sample.Type == ts.ElementaryStreamTypeH264 { + } + } +} + diff --git a/reader.go b/reader.go index 347481e..c50a719 100644 --- a/reader.go +++ b/reader.go @@ -56,7 +56,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) { } if debug { - fmt.Printf("ts: %s\n", FieldsDumper{ + fmt.Printf("ts: flags %s\n", FieldsDumper{ Fields: []struct{ Length int Desc string @@ -100,7 +100,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) { } if debug { - fmt.Printf("ts: %s\n", FieldsDumper{ + fmt.Printf("ts: ext_flags %s\n", FieldsDumper{ Fields: []struct{ Length int Desc string diff --git a/ts.go b/ts.go index bfebd1b..30b830d 100644 --- a/ts.go +++ b/ts.go @@ -18,6 +18,7 @@ type TSHeader struct { OPCR uint64 ContinuityCounter uint PayloadUnitStart bool + RandomAccessIndicator bool } type PATEntry struct { @@ -74,6 +75,12 @@ func UIntToPCR(v uint64) uint64 { return base*300+ext } +func PCRToUInt(pcr uint64) uint64 { + base := pcr/300 + ext := pcr%300 + return base<<15|0x3f<<9|ext +} + type FieldsDumper struct { Fields []struct { Length int diff --git a/writer.go b/writer.go index 6b5405c..8bce989 100644 --- a/writer.go +++ b/writer.go @@ -8,6 +8,103 @@ import ( type TSWriter struct { W io.Writer + ContinuityCounter uint + PayloadUnitStart bool +} + +func WriteUInt64(w io.Writer, val uint64, n int) (err error) { + var b [8]byte + for i := n-1; i >= 0; i-- { + b[i] = byte(val) + val >>= 8 + } + if _, err = w.Write(b[:]); err != nil { + return + } + return +} + +func WriteUInt(w io.Writer, val uint, n int) (err error) { + return WriteUInt64(w, uint64(val), n) +} + +func WriteTSHeader(w io.Writer, self TSHeader) (err error) { + var flags, extFlags uint + + // sync(8) + // transport_error_indicator(1) + // payload_unit_start_indicator(1) + // transport_priority(1) + // pid(13) + // Scrambling control(2) + // Adaptation field flag(1) 0x20 + // Payload flag(1) 0x10 + // Continuity counter(4) + + flags = 0x47<<24 + flags |= 0x10 + if self.PayloadUnitStart { + flags |= 0x400000 + } + flags |= (self.PID&0x1fff00)<<8 + flags |= self.ContinuityCounter&0xf + + if self.PCR != 0 { + extFlags |= 0x20 + } + if self.OPCR != 0 { + extFlags |= 0x08 + } + if self.RandomAccessIndicator { + extFlags |= 0x40 + } + + if extFlags != 0 { + flags |= 0x20 + } + + if err = WriteUInt(w, flags, 4); err != nil { + return + } + + if flags & 0x20 != 0 { + var length uint + + // Discontinuity indicator 1 0x80 + // Random Access indicator 1 0x40 + // Elementary stream priority indicator 1 0x20 + // PCR flag 1 0x10 + // OPCR flag 1 0x08 + + length = 1 + if extFlags & 0x10 != 0 { + length += 6 + } + if extFlags & 0x08 != 0 { + length += 6 + } + + if err = WriteUInt(w, length, 1); err != nil { + return + } + if err = WriteUInt(w, extFlags, 1); err != nil { + return + } + + if extFlags & 0x10 != 0 { + if err = WriteUInt64(w, PCRToUInt(self.PCR), 6); err != nil { + return + } + } + + if extFlags & 0x08 != 0 { + if err = WriteUInt64(w, PCRToUInt(self.OPCR), 6); err != nil { + return + } + } + } + + return } type PSIWriter struct {