joy4/format/ts/writer.go
2016-07-10 15:09:18 +08:00

211 lines
4.0 KiB
Go

package ts
import (
"bytes"
"fmt"
"io"
)
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[:n]); err != nil {
return
}
return
}
func WriteUInt(w io.Writer, val uint, n int) (err error) {
return WriteUInt64(w, uint64(val), n)
}
type TSWriter struct {
w io.Writer
ContinuityCounter uint
tshdr []byte
}
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)
// section_syntax_indicator(1)=1,private_bit(1)=1,reserved(2)=3,unused(2)=0,section_length(10)
// 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
}
// section_syntax_indicator(1)=1,private_bit(1)=0,reserved(2)=3,unused(2)=0,section_length(10)
var flags, length uint
length = 2 + 3 + 4 + uint(len(data))
flags = 0xa<<12 | length
if err = WriteUInt(cw, flags, 2); err != nil {
return
}
if DebugWriter {
fmt.Fprintf(DebugOutput, "psiw: length=%d\n", length)
}
// 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, bswap32(uint(cw.Crc32)), 4); err != nil {
return
}
return
}
func bswap32(v uint) uint {
return (v >> 24) | ((v>>16)&0xff)<<8 | ((v>>8)&0xff)<<16 | (v&0xff)<<24
}
func WritePAT(w io.Writer, self PAT) (err error) {
bw := &bytes.Buffer{}
for _, entry := range self.Entries {
if err = WriteUInt(bw, entry.ProgramNumber, 2); err != nil {
return
}
if entry.ProgramNumber == 0 {
if err = WriteUInt(bw, entry.NetworkPID&0x1fff|7<<13, 2); err != nil {
return
}
} else {
if err = WriteUInt(bw, entry.ProgramMapPID&0x1fff|7<<13, 2); err != nil {
return
}
}
}
psi := PSI{
TableIdExtension: 1,
}
if err = WritePSI(w, psi, bw.Bytes()); err != nil {
return
}
return
}
func WritePMT(w io.Writer, self PMT) (err error) {
writeDescs := func(w io.Writer, descs []Descriptor) (err error) {
for _, desc := range descs {
if err = WriteUInt(w, desc.Tag, 1); err != nil {
return
}
if err = WriteUInt(w, uint(len(desc.Data)), 1); err != nil {
return
}
if _, err = w.Write(desc.Data); err != nil {
return
}
}
return
}
writeBody := func(w io.Writer) (err error) {
if err = WriteUInt(w, self.PCRPID|7<<13, 2); err != nil {
return
}
bw := &bytes.Buffer{}
if err = writeDescs(bw, self.ProgramDescriptors); err != nil {
return
}
if err = WriteUInt(w, 0xf<<12|uint(bw.Len()), 2); err != nil {
return
}
if _, err = w.Write(bw.Bytes()); err != nil {
return
}
for _, info := range self.ElementaryStreamInfos {
if err = WriteUInt(w, info.StreamType, 1); err != nil {
return
}
// Reserved(3)
// Elementary PID(13)
if err = WriteUInt(w, info.ElementaryPID|7<<13, 2); err != nil {
return
}
bw := &bytes.Buffer{}
if err = writeDescs(bw, info.Descriptors); err != nil {
return
}
// Reserved(6)
// ES Info length length(10)
if err = WriteUInt(w, uint(bw.Len())|0x3c<<10, 2); err != nil {
return
}
if _, err = w.Write(bw.Bytes()); err != nil {
return
}
}
return
}
bw := &bytes.Buffer{}
if err = writeBody(bw); err != nil {
return
}
psi := PSI{
TableId: 2,
TableIdExtension: 1,
}
if err = WritePSI(w, psi, bw.Bytes()); err != nil {
return
}
return
}