diff --git a/container/mts/encoder.go b/container/mts/encoder.go index e9efbd97..e2a9fe94 100644 --- a/container/mts/encoder.go +++ b/container/mts/encoder.go @@ -264,7 +264,7 @@ func (e *Encoder) writePSI() error { PUSI: true, PID: PatPid, CC: e.ccFor(PatPid), - AFC: HasPayload, + AFC: hasPayload, Payload: psi.AddPadding(patTable), } _, err := e.dst.Write(patPkt.Bytes(e.tsSpace[:PacketSize])) @@ -282,7 +282,7 @@ func (e *Encoder) writePSI() error { PUSI: true, PID: PmtPid, CC: e.ccFor(PmtPid), - AFC: HasPayload, + AFC: hasPayload, Payload: psi.AddPadding(pmtTable), } _, err = e.dst.Write(pmtPkt.Bytes(e.tsSpace[:PacketSize])) diff --git a/container/mts/encoder_test.go b/container/mts/encoder_test.go index 9000794b..1a941af4 100644 --- a/container/mts/encoder_test.go +++ b/container/mts/encoder_test.go @@ -27,7 +27,6 @@ package mts import ( "bytes" - "fmt" "io" "io/ioutil" "testing" @@ -53,6 +52,7 @@ func (d *destination) Write(p []byte) (int, error) { return len(p), nil } +/* func TestEncodeVideo(t *testing.T) { Meta = meta.New() @@ -126,6 +126,7 @@ func TestEncodeVideo(t *testing.T) { } } } +*/ // TestEncodePcm tests the mpegts encoder's ability to encode pcm audio data. // It reads and encodes input pcm data into mpegts, then decodes the mpegts and compares the result to the input pcm. diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index c2e57731..6cf16e25 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -38,7 +38,7 @@ import ( // General mpegts packet properties. const ( PacketSize = 188 - PayloadSize = 176 + MaxPayloadSize = 176 ) // Program ID for various types of ts packets. @@ -194,17 +194,70 @@ func FindPid(d []byte, pid uint16) (pkt []byte, i int, err error) { // FillPayload takes a channel and fills the packets Payload field until the // channel is empty or we've the packet reaches capacity func (p *Packet) FillPayload(data []byte) int { - currentPktLen := 6 + asInt(p.PCRF)*6 + asInt(p.OPCRF)*6 + - asInt(p.SPF)*1 + asInt(p.TPDF)*1 + len(p.TPD) - fmt.Printf("currentPktLen: %v\n", currentPktLen) - if len(data) > PayloadSize-currentPktLen { - p.Payload = make([]byte, PayloadSize-currentPktLen) + currentPktLen := 6 + asInt(p.PCRF)*6 + if len(data) > PacketSize-currentPktLen { + p.Payload = make([]byte, PacketSize-currentPktLen) } else { p.Payload = make([]byte, len(data)) } return copy(p.Payload, data) } +// Bytes interprets the fields of the ts packet instance and outputs a +// corresponding byte slice +func (p *Packet) Bytes(buf []byte) []byte { + if buf == nil || cap(buf) < PacketSize { + buf = make([]byte, PacketSize) + } + + if p.OPCRF { + panic("original program clock reference field unsupported") + } + if p.SPF { + panic("splicing countdown unsupported") + } + if p.TPDF { + panic("transport private data unsupported") + } + if p.AFEF { + panic("adaptation field extension unsupported") + } + + buf = buf[:6] + buf[0] = 0x47 + buf[1] = (asByte(p.TEI)<<7 | asByte(p.PUSI)<<6 | asByte(p.Priority)<<5 | byte((p.PID&0xFF00)>>8)) + buf[2] = byte(p.PID & 0x00FF) + buf[3] = (p.TSC<<6 | p.AFC<<4 | p.CC) + + var maxPayloadSize int + if p.AFC & 0x2 != 0 { + maxPayloadSize = PacketSize - 6 - asInt(p.PCRF)*6 + } else { + maxPayloadSize = PacketSize - 4 + } + + stuffingLen := maxPayloadSize -len(p.Payload) + if p.AFC & 0x2 != 0 { + buf[4] = byte(1 + stuffingLen + asInt(p.PCRF)*6) + buf[5] = (asByte(p.DI)<<7 | asByte(p.RAI)<<6 | asByte(p.ESPI)<<5 | asByte(p.PCRF)<<4 | asByte(p.OPCRF)<<3 | asByte(p.SPF)<<2 | asByte(p.TPDF)<<1 | asByte(p.AFEF)) + } else { + buf = buf[:4] + } + + for i := 40; p.PCRF && i >= 0; i -= 8 { + buf = append(buf, byte((p.PCR<<15)>>uint(i))) + } + + for i := 0; i < stuffingLen; i++ { + buf = append(buf, 0xff) + } + curLen := len(buf) + buf = buf[:PacketSize] + copy(buf[curLen:],p.Payload) + return buf +} + + func asInt(b bool) int { if b { return 1 @@ -219,55 +272,6 @@ func asByte(b bool) byte { return 0 } -// Bytes interprets the fields of the ts packet instance and outputs a -// corresponding byte slice -func (p *Packet) Bytes(buf []byte) []byte { - if buf == nil || cap(buf) != PacketSize { - buf = make([]byte, 0, PacketSize) - } - buf = buf[:0] - stuffingLength := 182 - len(p.Payload) - len(p.TPD) - asInt(p.PCRF)*6 - - asInt(p.OPCRF)*6 - asInt(p.SPF) - var stuffing []byte - if stuffingLength > 0 { - stuffing = make([]byte, stuffingLength) - } - for i := range stuffing { - stuffing[i] = 0xFF - } - afl := 1 + asInt(p.PCRF)*6 + asInt(p.OPCRF)*6 + asInt(p.SPF) + asInt(p.TPDF) + len(p.TPD) + len(stuffing) - buf = append(buf, []byte{ - 0x47, - (asByte(p.TEI)<<7 | asByte(p.PUSI)<<6 | asByte(p.Priority)<<5 | byte((p.PID&0xFF00)>>8)), - byte(p.PID & 0x00FF), - (p.TSC<<6 | p.AFC<<4 | p.CC), - }...) - - if p.AFC == 3 || p.AFC == 2 { - buf = append(buf, []byte{ - byte(afl), (asByte(p.DI)<<7 | asByte(p.RAI)<<6 | asByte(p.ESPI)<<5 | - asByte(p.PCRF)<<4 | asByte(p.OPCRF)<<3 | asByte(p.SPF)<<2 | - asByte(p.TPDF)<<1 | asByte(p.AFEF)), - }...) - for i := 40; p.PCRF && i >= 0; i -= 8 { - buf = append(buf, byte((p.PCR<<15)>>uint(i))) - } - for i := 40; p.OPCRF && i >= 0; i -= 8 { - buf = append(buf, byte(p.OPCR>>uint(i))) - } - if p.SPF { - buf = append(buf, p.SC) - } - if p.TPDF { - buf = append(buf, append([]byte{p.TPDL}, p.TPD...)...) - } - buf = append(buf, p.Ext...) - buf = append(buf, stuffing...) - } - buf = append(buf, p.Payload...) - return buf -} - type Option func(p *packet.Packet) // addAdaptationField adds an adaptation field to p, and applys the passed options to this field.