add Muxer

This commit is contained in:
nareix 2016-03-06 16:10:40 +08:00
parent f080de0350
commit 4b857a6eed

166
muxer.go Normal file
View File

@ -0,0 +1,166 @@
package ts
import (
"bytes"
"io"
)
type Track struct {
timeScale int64
writeSPS bool
SPS []byte
PPS []byte
spsHasWritten bool
tsw *TSWriter
PTS int64
PCR int64
pesBuf *bytes.Buffer
}
func (self *Track) WriteH264NALU(sync bool, duration int, nalu []byte) (err error) {
nalus := [][]byte{}
if !self.spsHasWritten {
nalus = append(nalus, self.SPS)
nalus = append(nalus, self.PPS)
self.spsHasWritten = true
}
nalus = append(nalus, nalu)
pes := PESHeader{
StreamId: StreamIdH264,
PTS: uint64(self.PTS)*PTS_HZ/uint64(self.timeScale),
}
if err = WritePESHeader(self.pesBuf, pes); err != nil {
return
}
data := &iovec{}
data.Append(self.pesBuf.Bytes())
for i, nalu := range nalus {
var startCode []byte
if i == 0 {
startCode = []byte{0,0,0,1,0x9,0xf0,0,0,0,1} // AUD
} else {
startCode = []byte{0,0,1}
}
data.Append(startCode)
data.Append(nalu)
}
self.tsw.RandomAccessIndicator = sync
self.tsw.PCR = uint64(self.PCR)*PCR_HZ/uint64(self.timeScale)
if err = self.tsw.WriteIovec(data); err != nil {
return
}
self.PTS += int64(duration)
self.PCR += int64(duration)
self.pesBuf.Reset()
return
}
func (self *Track) WriteADTSAACFrame(duration int, frame []byte) (err error) {
pes := PESHeader{
StreamId: StreamIdAAC,
PTS: uint64(self.PTS)*PTS_HZ/uint64(self.timeScale),
}
if err = WritePESHeader(self.pesBuf, pes); err != nil {
return
}
data := &iovec{}
data.Append(self.pesBuf.Bytes())
data.Append(frame)
self.tsw.RandomAccessIndicator = true
self.tsw.PCR = uint64(self.PCR)*PCR_HZ/uint64(self.timeScale)
if err = self.tsw.WriteIovec(data); err != nil {
return
}
self.PTS += int64(duration)
self.PCR += int64(duration)
self.pesBuf.Reset()
return
}
func newTrack(w io.Writer, pid uint, timeScale int64) (track *Track) {
track = &Track{
tsw: &TSWriter{
W: w,
PID: pid,
DiscontinuityIndicator: true,
},
timeScale: timeScale,
pesBuf: &bytes.Buffer{},
}
track.tsw.EnableVecWriter()
track.PTS = timeScale
track.PCR = timeScale
return
}
type Muxer struct {
W io.Writer
TimeScale int64
tswPAT *TSWriter
tswPMT *TSWriter
elemStreams []ElementaryStreamInfo
}
func (self *Muxer) AddAACTrack() (track *Track) {
self.elemStreams = append(
self.elemStreams,
ElementaryStreamInfo{StreamType: ElementaryStreamTypeAdtsAAC, ElementaryPID: 0x101},
)
return newTrack(self.W, 0x101, self.TimeScale)
}
func (self *Muxer) AddH264Track() (track *Track) {
self.elemStreams = append(
self.elemStreams,
ElementaryStreamInfo{StreamType: ElementaryStreamTypeH264, ElementaryPID: 0x100},
)
return newTrack(self.W, 0x100, self.TimeScale)
}
func (self *Muxer) WriteHeader() (err error) {
bufPAT := &bytes.Buffer{}
bufPMT := &bytes.Buffer{}
pat := PAT{
Entries: []PATEntry{
{ProgramNumber: 1, ProgramMapPID: 0x1000},
},
}
WritePAT(bufPAT, pat)
pmt := PMT{
PCRPID: 0x100,
ElementaryStreamInfos: self.elemStreams,
}
WritePMT(bufPMT, pmt)
tswPMT := &TSWriter{
W: self.W,
PID: 0x1000,
DiscontinuityIndicator: true,
}
tswPAT := &TSWriter{
W: self.W,
PID: 0,
DiscontinuityIndicator: true,
}
if err = tswPAT.Write(bufPAT.Bytes()); err != nil {
return
}
if err = tswPMT.Write(bufPMT.Bytes()); err != nil {
return
}
return
}