adjust PTS/PCR/TimeScale in Muxer
This commit is contained in:
parent
4b857a6eed
commit
443a7e4869
@ -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
114
muxer.go
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user