adjust PTS/PCR/TimeScale in Muxer

This commit is contained in:
nareix 2016-03-07 17:19:12 +08:00
parent 4b857a6eed
commit 443a7e4869
2 changed files with 78 additions and 63 deletions

View File

@ -211,15 +211,16 @@ func testInputGob(pathGob string, pathOut string, testSeg bool, writeM3u8 bool)
writeM3U8Header(m3u8file) writeM3U8Header(m3u8file)
} }
w := ts.SimpleH264Writer{ muxer := &ts.Muxer{
W: outfile, W: outfile,
SPS: allSamples.SPS,
PPS: allSamples.PPS,
TimeScale: allSamples.TimeScale,
} }
lastPCR := int64(0) trackH264 := muxer.AddH264Track()
//w.WriteHeader() trackH264.SPS = allSamples.SPS
trackH264.PPS = allSamples.PPS
trackH264.TimeScale = int64(allSamples.TimeScale)
muxer.WriteHeader()
lastPTS := int64(0)
syncCount := 0 syncCount := 0
segCount := 0 segCount := 0
@ -234,13 +235,13 @@ func testInputGob(pathGob string, pathOut string, testSeg bool, writeM3u8 bool)
filename := fmt.Sprintf("%s.seg%d.ts", pathOut, segCount) filename := fmt.Sprintf("%s.seg%d.ts", pathOut, segCount)
if debugStream { if debugStream {
fmt.Println("stream:", "seg", segCount, "sync", syncCount, w.PCR) fmt.Println("stream:", "seg", segCount, "sync", syncCount, trackH264.PTS)
} }
if m3u8file != nil { if m3u8file != nil {
info, _ := outfile.Stat() info, _ := outfile.Stat()
size := info.Size() size := info.Size()
dur := float64(w.PCR - lastPCR) / float64(allSamples.TimeScale) dur := float64(trackH264.PTS - lastPTS) / float64(allSamples.TimeScale)
writeM3U8Item(m3u8file, lastFilename, size, dur) writeM3U8Item(m3u8file, lastFilename, size, dur)
} }
@ -248,14 +249,14 @@ func testInputGob(pathGob string, pathOut string, testSeg bool, writeM3u8 bool)
outfile.Close() outfile.Close()
segCount++ segCount++
outfile, _ = os.Create(filename) outfile, _ = os.Create(filename)
w.W = outfile muxer.W = outfile
w.WriteHeader() muxer.WriteHeader()
lastPCR = w.PCR lastPTS = trackH264.PTS
} }
} }
} }
w.WriteNALU(sample.Sync, sample.Duration, sample.Data)
trackH264.WriteH264NALU(sample.Sync, sample.Duration, sample.Data)
} }
if m3u8file != nil { if m3u8file != nil {

114
muxer.go
View File

@ -7,15 +7,46 @@ import (
) )
type Track struct { type Track struct {
timeScale int64
writeSPS bool
SPS []byte SPS []byte
PPS []byte PPS []byte
spsHasWritten bool
tsw *TSWriter
PTS int64 PTS int64
PCR int64 TimeScale int64
pesBuf *bytes.Buffer
writeSPS bool
spsHasWritten bool
pcrHasWritten bool
streamId uint
tsw *TSWriter
dataBuf *iovec
cacheSize int
}
func (self *Track) setPCR() {
if !self.pcrHasWritten {
self.tsw.PCR = 24300000
self.pcrHasWritten = true
} else {
self.tsw.PCR = 0
}
}
func (self *Track) getPesHeader() (data []byte){
if self.PTS == 0 {
self.PTS = self.TimeScale
}
buf := &bytes.Buffer{}
pes := PESHeader{
StreamId: self.streamId,
PTS: uint64(self.PTS)*PTS_HZ/uint64(self.TimeScale),
}
WritePESHeader(buf, pes)
return buf.Bytes()
}
func (self *Track) incPTS(delta int) {
self.PTS += int64(delta)
} }
func (self *Track) WriteH264NALU(sync bool, duration int, nalu []byte) (err error) { func (self *Track) WriteH264NALU(sync bool, duration int, nalu []byte) (err error) {
@ -28,16 +59,8 @@ func (self *Track) WriteH264NALU(sync bool, duration int, nalu []byte) (err erro
} }
nalus = append(nalus, nalu) 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 := &iovec{}
data.Append(self.pesBuf.Bytes()) data.Append(self.getPesHeader())
for i, nalu := range nalus { for i, nalu := range nalus {
var startCode []byte var startCode []byte
if i == 0 { if i == 0 {
@ -50,64 +73,51 @@ func (self *Track) WriteH264NALU(sync bool, duration int, nalu []byte) (err erro
} }
self.tsw.RandomAccessIndicator = sync self.tsw.RandomAccessIndicator = sync
self.tsw.PCR = uint64(self.PCR)*PCR_HZ/uint64(self.timeScale) self.setPCR()
if err = self.tsw.WriteIovec(data); err != nil { if err = self.tsw.WriteIovec(data); err != nil {
return return
} }
self.PTS += int64(duration) self.incPTS(duration)
self.PCR += int64(duration)
self.pesBuf.Reset()
return return
} }
func (self *Track) WriteADTSAACFrame(duration int, frame []byte) (err error) { func (self *Track) WriteADTSAACFrame(duration int, frame []byte) (err error) {
pes := PESHeader{ if self.dataBuf != nil && self.dataBuf.Len > self.cacheSize {
StreamId: StreamIdAAC, self.tsw.RandomAccessIndicator = true
PTS: uint64(self.PTS)*PTS_HZ/uint64(self.timeScale), self.setPCR()
} if err = self.tsw.WriteIovec(self.dataBuf); err != nil {
if err = WritePESHeader(self.pesBuf, pes); err != nil { return
return }
self.dataBuf = nil
} }
data := &iovec{} if self.dataBuf == nil {
data.Append(self.pesBuf.Bytes()) self.dataBuf = &iovec{}
data.Append(frame) self.dataBuf.Append(self.getPesHeader())
} else {
self.tsw.RandomAccessIndicator = true self.dataBuf.Append(frame)
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.incPTS(duration)
self.PCR += int64(duration)
self.pesBuf.Reset()
return return
} }
func newTrack(w io.Writer, pid uint, timeScale int64) (track *Track) { func newTrack(w io.Writer, pid uint, streamId uint) (track *Track) {
track = &Track{ track = &Track{
tsw: &TSWriter{ tsw: &TSWriter{
W: w, W: w,
PID: pid, PID: pid,
DiscontinuityIndicator: true, //DiscontinuityIndicator: true,
}, },
timeScale: timeScale, streamId: streamId,
pesBuf: &bytes.Buffer{},
} }
track.tsw.EnableVecWriter() track.tsw.EnableVecWriter()
track.PTS = timeScale
track.PCR = timeScale
return return
} }
type Muxer struct { type Muxer struct {
W io.Writer W io.Writer
TimeScale int64
tswPAT *TSWriter tswPAT *TSWriter
tswPMT *TSWriter tswPMT *TSWriter
elemStreams []ElementaryStreamInfo elemStreams []ElementaryStreamInfo
@ -118,7 +128,10 @@ func (self *Muxer) AddAACTrack() (track *Track) {
self.elemStreams, self.elemStreams,
ElementaryStreamInfo{StreamType: ElementaryStreamTypeAdtsAAC, ElementaryPID: 0x101}, ElementaryStreamInfo{StreamType: ElementaryStreamTypeAdtsAAC, ElementaryPID: 0x101},
) )
return newTrack(self.W, 0x101, self.TimeScale) track = newTrack(self.W, 0x101, StreamIdAAC)
track.pcrHasWritten = true
track.cacheSize = 3000
return
} }
func (self *Muxer) AddH264Track() (track *Track) { func (self *Muxer) AddH264Track() (track *Track) {
@ -126,7 +139,8 @@ func (self *Muxer) AddH264Track() (track *Track) {
self.elemStreams, self.elemStreams,
ElementaryStreamInfo{StreamType: ElementaryStreamTypeH264, ElementaryPID: 0x100}, ElementaryStreamInfo{StreamType: ElementaryStreamTypeH264, ElementaryPID: 0x100},
) )
return newTrack(self.W, 0x100, self.TimeScale) track = newTrack(self.W, 0x100, StreamIdH264)
return
} }
func (self *Muxer) WriteHeader() (err error) { func (self *Muxer) WriteHeader() (err error) {
@ -148,12 +162,12 @@ func (self *Muxer) WriteHeader() (err error) {
tswPMT := &TSWriter{ tswPMT := &TSWriter{
W: self.W, W: self.W,
PID: 0x1000, PID: 0x1000,
DiscontinuityIndicator: true, //DiscontinuityIndicator: true,
} }
tswPAT := &TSWriter{ tswPAT := &TSWriter{
W: self.W, W: self.W,
PID: 0, PID: 0,
DiscontinuityIndicator: true, //DiscontinuityIndicator: true,
} }
if err = tswPAT.Write(bufPAT.Bytes()); err != nil { if err = tswPAT.Write(bufPAT.Bytes()); err != nil {
return return