From 13160821be99b600341d637649288547fc8e47ed Mon Sep 17 00:00:00 2001 From: nareix Date: Sat, 5 Dec 2015 23:09:48 +0800 Subject: [PATCH] add WritePES/PSI --- checksum.go | 17 ++++-- reader.go | 6 +- ts.go | 5 ++ writer.go | 155 +++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 167 insertions(+), 16 deletions(-) diff --git a/checksum.go b/checksum.go index ae73093..6c2d97e 100644 --- a/checksum.go +++ b/checksum.go @@ -67,10 +67,6 @@ type Crc32Reader struct { var debugCrc32 = false -func NewCrc32Reader(r io.Reader) *Crc32Reader { - return &Crc32Reader{R: r, Crc32: 0xffffffff} -} - func (self *Crc32Reader) Read(b []byte) (n int, err error) { if n, err = self.R.Read(b); err != nil { return @@ -93,3 +89,16 @@ func (self *Crc32Reader) ReadCrc32UIntAndCheck() (err error) { return } +type Crc32Writer struct { + W io.Writer + Crc32 uint32 +} + +func (self *Crc32Writer) Write(b []byte) (n int, err error) { + if n, err = self.W.Write(b); err != nil { + return + } + self.Crc32 = updateIeeeCrc32(self.Crc32, b) + return +} + diff --git a/reader.go b/reader.go index c50a719..8b2b154 100644 --- a/reader.go +++ b/reader.go @@ -202,7 +202,7 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err } } - cr = NewCrc32Reader(r) + cr = &Crc32Reader{R: r, Crc32: 0xffffffff} // table_id if self.TableId, err = ReadUInt(cr, 1); err != nil { @@ -463,8 +463,8 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) { Length int Desc string }{ - {2, "PES_scrambling_control"}, - {1, "PES_priority"}, + {2, "scrambling_control"}, + {1, "priority"}, {1, "data_alignment_indicator"}, {1, "copyright"}, {1, "original_or_copy"}, diff --git a/ts.go b/ts.go index 30b830d..c59ade7 100644 --- a/ts.go +++ b/ts.go @@ -68,6 +68,11 @@ func PESUIntToTs(v uint64) (ts uint64) { return (((v>>33)&0x7)<<30) | (((v>>17)&0x7fff)<<15) | ((v>>1)&0x7fff) } +func PESTsToUInt(ts uint64) (v uint64) { + // 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1 + return ((ts>>30)&0x7)<<33 | ((ts>>15)&0x7fff)<<17 | (v&0x7fff)<<1 | 0x100010001 +} + func UIntToPCR(v uint64) uint64 { // base(33)+resverd(6)+ext(9) base := v>>15 diff --git a/writer.go b/writer.go index 8bce989..e7cfac8 100644 --- a/writer.go +++ b/writer.go @@ -107,20 +107,157 @@ func WriteTSHeader(w io.Writer, self TSHeader) (err error) { return } -type PSIWriter struct { - W *TSWriter -} +func WritePSI(w io.Writer, self PSI, data []byte) (err error) { + // pointer(8) + // table_id(8) + // reserved(4)=0xb,section_length(10) + // Table ID extension(16) + // resverd(2)=3,version(5),Current_next_indicator(1) + // section_number(8) + // last_section_number(8) + // data + // crc(32) + + // pointer(8) + if err = WriteUInt(w, 0, 1); err != nil { + return + } + + cw := &Crc32Writer{W: w, Crc32: 0xffffffff} + + // table_id(8) + if err = WriteUInt(cw, self.TableId, 1); err != nil { + return + } + + // reserved(4)=0xb,section_length(10) + var flags, length uint + length = 2+3+4+uint(len(data)) + flags = 0xb<<10|length + if err = WriteUInt(cw, flags, 1); err != nil { + return + } + + // Table ID extension(16) + if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil { + return + } + + // resverd(2)=3,version(5)=0,Current_next_indicator(1)=1 + flags = 0x3<<6|1 + if err = WriteUInt(cw, flags, 1); err != nil { + return + } + + // section_number(8) + if err = WriteUInt(cw, self.SecNum, 1); err != nil { + return + } + + // last_section_number(8) + if err = WriteUInt(cw, self.LastSecNum, 1); err != nil { + return + } + + // data + if _, err = cw.Write(data); err != nil { + return + } + + // crc(32) + if err = WriteUInt(w, uint(cw.Crc32), 4); err != nil { + return + } -func (self PSIWriter) Write(b []byte) (err error) { return } -func (self PSIWriter) Finish() (err error) { - return -} +func WritePES(w io.Writer, self PESHeader, data []byte) (err error) { + // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html -type PESWriter struct { - W io.Writer + var pts_dts_flags, header_length, packet_length uint + + // start code(24) 000001 + // StreamId(8) + // packet_length(16) + // resverd(6,2)=2,original_or_copy(0,1)=1 + // pts_dts_flags(6,2) + // header_length(8) + // pts(40)? + // dts(40)? + // data + + // start code(24) 000001 + if err = WriteUInt(w, 0x000001, 3); err != nil { + return + } + + // StreamId(8) + if err = WriteUInt(w, self.StreamId, 1); err != nil { + return + } + + const PTS = 1<<7 + const DTS = 1<<6 + + if self.PTS != 0 { + pts_dts_flags |= PTS + if self.DTS != 0 { + pts_dts_flags |= DTS + } + } + + if pts_dts_flags & PTS != 0 { + header_length += 5 + } + if pts_dts_flags & DTS != 0 { + header_length += 5 + } + packet_length = 3+header_length+uint(len(data)) + + // packet_length(16) + if err = WriteUInt(w, packet_length, 2); err != nil { + return + } + + // resverd(6,2)=2,original_or_copy(0,1)=1 + if err = WriteUInt(w, 2<<6|1, 1); err != nil { + return + } + + // pts_dts_flags(6,2) + if err = WriteUInt(w, pts_dts_flags, 1); err != nil { + return + } + + // header_length(8) + if err = WriteUInt(w, header_length, 1); err != nil { + return + } + + // pts(40)? + // dts(40)? + if pts_dts_flags & PTS != 0 { + if pts_dts_flags & DTS != 0 { + if err = WriteUInt64(w, PESTsToUInt(self.PTS)|3<<36, 5); err != nil { + return + } + if err = WriteUInt64(w, PESTsToUInt(self.DTS)|1<<36, 5); err != nil { + return + } + } else { + if err = WriteUInt64(w, PESTsToUInt(self.PTS)|2<<36, 5); err != nil { + return + } + } + } + + // data + if _, err = w.Write(data); err != nil { + return + } + + return } type SimpleH264Writer struct {