hls: send PCR once, at the beginning of every TS segment

This commit is contained in:
aler9 2021-08-14 17:25:40 +02:00
parent 2d71e69e43
commit 93b143395e
2 changed files with 39 additions and 25 deletions

View file

@ -34,7 +34,6 @@ type Muxer struct {
h264SPS []byte
h264PPS []byte
aacConfig rtpaac.MPEG4AudioConfig
startPCR time.Time
videoDTSEst *h264.DTSEstimator
audioAUCount int
tsCurrent *tsFile
@ -42,6 +41,7 @@ type Muxer struct {
tsByName map[string]*tsFile
tsDeleteCount int
mutex sync.RWMutex
startPCR time.Time
startPTS time.Duration
}
@ -82,7 +82,6 @@ func NewMuxer(
h264SPS: h264SPS,
h264PPS: h264PPS,
aacConfig: aacConfig,
startPCR: time.Now(),
videoDTSEst: h264.NewDTSEstimator(),
tsCurrent: newTSFile(videoTrack, audioTrack),
tsByName: make(map[string]*tsFile),
@ -122,11 +121,10 @@ func (m *Muxer) WriteH264(pts time.Duration, nalus [][]byte) error {
if idrPresent &&
m.tsCurrent.firstPacketWritten &&
m.tsCurrent.duration() >= m.hlsSegmentDuration {
if m.tsCurrent != nil {
m.tsCurrent.close()
}
m.tsCurrent.close()
m.tsCurrent = newTSFile(m.videoTrack, m.audioTrack)
m.tsCurrent.setStartPCR(m.startPCR)
m.tsByName[m.tsCurrent.name] = m.tsCurrent
m.tsQueue = append(m.tsQueue, m.tsCurrent)
@ -136,11 +134,12 @@ func (m *Muxer) WriteH264(pts time.Duration, nalus [][]byte) error {
m.tsDeleteCount++
}
} else if !m.tsCurrent.firstPacketWritten {
m.startPCR = time.Now()
m.startPTS = pts
m.tsCurrent.setStartPCR(m.startPCR)
}
pts = pts + ptsOffset - m.startPTS
m.tsCurrent.setPCR(time.Since(m.startPCR))
err := m.tsCurrent.writeH264(
m.h264SPS,
m.h264PPS,
@ -164,13 +163,13 @@ func (m *Muxer) WriteAAC(pts time.Duration, aus [][]byte) error {
if m.audioAUCount >= segmentMinAUCount &&
m.tsCurrent.firstPacketWritten &&
m.tsCurrent.duration() >= m.hlsSegmentDuration {
if m.tsCurrent != nil {
m.tsCurrent.close()
}
m.tsCurrent.close()
m.audioAUCount = 0
m.tsCurrent = newTSFile(m.videoTrack, m.audioTrack)
m.tsCurrent.setStartPCR(m.startPCR)
m.tsByName[m.tsCurrent.name] = m.tsCurrent
m.tsQueue = append(m.tsQueue, m.tsCurrent)
if len(m.tsQueue) > m.hlsSegmentCount {
@ -179,7 +178,9 @@ func (m *Muxer) WriteAAC(pts time.Duration, aus [][]byte) error {
m.tsDeleteCount++
}
} else if !m.tsCurrent.firstPacketWritten {
m.startPCR = time.Now()
m.startPTS = pts
m.tsCurrent.setStartPCR(m.startPCR)
}
} else {
if !m.tsCurrent.firstPacketWritten {
@ -192,8 +193,6 @@ func (m *Muxer) WriteAAC(pts time.Duration, aus [][]byte) error {
for i, au := range aus {
auPTS := pts + time.Duration(i)*1000*time.Second/time.Duration(m.aacConfig.SampleRate)
m.audioAUCount++
m.tsCurrent.setPCR(time.Since(m.startPCR))
err := m.tsCurrent.writeAAC(
m.aacConfig.SampleRate,
m.aacConfig.ChannelCount,
@ -202,6 +201,8 @@ func (m *Muxer) WriteAAC(pts time.Duration, aus [][]byte) error {
if err != nil {
return err
}
m.audioAUCount++
}
return nil

View file

@ -18,10 +18,10 @@ type tsFile struct {
name string
buf *multiAccessBuffer
mux *astits.Muxer
pcr time.Duration
firstPacketWritten bool
minPTS time.Duration
maxPTS time.Duration
startPCR time.Time
}
func newTSFile(videoTrack *gortsplib.Track, audioTrack *gortsplib.Track) *tsFile {
@ -69,8 +69,8 @@ func (t *tsFile) duration() time.Duration {
return t.maxPTS - t.minPTS
}
func (t *tsFile) setPCR(pcr time.Duration) {
t.pcr = pcr
func (t *tsFile) setStartPCR(startPCR time.Time) {
t.startPCR = startPCR
}
func (t *tsFile) newReader() io.Reader {
@ -81,7 +81,6 @@ func (t *tsFile) writeH264(
h264SPS []byte, h264PPS []byte,
dts time.Duration, pts time.Duration, isIDR bool, nalus [][]byte) error {
if !t.firstPacketWritten {
t.firstPacketWritten = true
t.minPTS = pts
t.maxPTS = pts
} else {
@ -115,17 +114,30 @@ func (t *tsFile) writeH264(
filteredNALUs = append(filteredNALUs, nalu)
}
var af *astits.PacketAdaptationField
if isIDR {
if af == nil {
af = &astits.PacketAdaptationField{}
}
af.RandomAccessIndicator = true
}
if !t.firstPacketWritten {
t.firstPacketWritten = true
if af == nil {
af = &astits.PacketAdaptationField{}
}
af.HasPCR = true
pcr := time.Since(t.startPCR)
af.PCR = &astits.ClockReference{Base: int64(pcr.Seconds() * 90000)}
}
enc, err := h264.EncodeAnnexB(filteredNALUs)
if err != nil {
return err
}
af := &astits.PacketAdaptationField{
RandomAccessIndicator: isIDR,
HasPCR: true,
PCR: &astits.ClockReference{Base: int64(t.pcr.Seconds() * 90000)},
}
_, err = t.mux.WriteData(&astits.MuxerData{
PID: 256,
AdaptationField: af,
@ -148,7 +160,6 @@ func (t *tsFile) writeH264(
func (t *tsFile) writeAAC(sampleRate int, channelCount int, pts time.Duration, au []byte) error {
if t.videoTrack == nil {
if !t.firstPacketWritten {
t.firstPacketWritten = true
t.minPTS = pts
t.maxPTS = pts
} else {
@ -176,9 +187,11 @@ func (t *tsFile) writeAAC(sampleRate int, channelCount int, pts time.Duration, a
RandomAccessIndicator: true,
}
if t.videoTrack == nil {
if t.videoTrack == nil && !t.firstPacketWritten {
t.firstPacketWritten = true
af.HasPCR = true
af.PCR = &astits.ClockReference{Base: int64(t.pcr.Seconds() * 90000)}
pcr := time.Since(t.startPCR)
af.PCR = &astits.ClockReference{Base: int64(pcr.Seconds() * 90000)}
}
_, err = t.mux.WriteData(&astits.MuxerData{