mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-25 12:32:01 -08:00
hls: send PCR once, at the beginning of every TS segment
This commit is contained in:
parent
2d71e69e43
commit
93b143395e
2 changed files with 39 additions and 25 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue