Skip to content

Commit

Permalink
hls: send PCR once, at the beginning of every TS segment
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed Aug 14, 2021
1 parent 2d71e69 commit 93b1433
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 25 deletions.
25 changes: 13 additions & 12 deletions internal/hls/muxer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ type Muxer struct {
h264SPS []byte
h264PPS []byte
aacConfig rtpaac.MPEG4AudioConfig
startPCR time.Time
videoDTSEst *h264.DTSEstimator
audioAUCount int
tsCurrent *tsFile
tsQueue []*tsFile
tsByName map[string]*tsFile
tsDeleteCount int
mutex sync.RWMutex
startPCR time.Time
startPTS time.Duration
}

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand All @@ -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,
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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,
Expand All @@ -202,6 +201,8 @@ func (m *Muxer) WriteAAC(pts time.Duration, aus [][]byte) error {
if err != nil {
return err
}

m.audioAUCount++
}

return nil
Expand Down
39 changes: 26 additions & 13 deletions internal/hls/tsfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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{
Expand Down

0 comments on commit 93b1433

Please sign in to comment.