force all readers to use an asynchronous writer (#2265)

needed by #2255
This commit is contained in:
Alessandro Ros 2023-08-30 11:24:14 +02:00 committed by GitHub
parent 30a69a7722
commit 5fb7f4e846
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 962 additions and 938 deletions

View file

@ -10,12 +10,15 @@ import (
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/asyncwriter"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
)
type readerFunc func(unit.Unit) error
// Stream is a media stream.
// It stores tracks, readers and allow to write data to readers.
// It stores tracks, readers and allows to write data to readers.
type Stream struct {
desc *description.Session
bytesReceived *uint64
@ -62,7 +65,7 @@ func (s *Stream) Close() {
}
}
// Desc returns description of the stream.
// Desc returns the description of the stream.
func (s *Stream) Desc() *description.Session {
return s.desc
}
@ -90,7 +93,7 @@ func (s *Stream) RTSPSStream(server *gortsplib.Server) *gortsplib.ServerStream {
}
// AddReader adds a reader.
func (s *Stream) AddReader(r interface{}, medi *description.Media, forma format.Format, cb func(unit.Unit)) {
func (s *Stream) AddReader(r *asyncwriter.Writer, medi *description.Media, forma format.Format, cb readerFunc) {
s.mutex.Lock()
defer s.mutex.Unlock()
@ -100,7 +103,7 @@ func (s *Stream) AddReader(r interface{}, medi *description.Media, forma format.
}
// RemoveReader removes a reader.
func (s *Stream) RemoveReader(r interface{}) {
func (s *Stream) RemoveReader(r *asyncwriter.Writer) {
s.mutex.Lock()
defer s.mutex.Unlock()
@ -112,14 +115,14 @@ func (s *Stream) RemoveReader(r interface{}) {
}
// WriteUnit writes a Unit.
func (s *Stream) WriteUnit(medi *description.Media, forma format.Format, data unit.Unit) {
func (s *Stream) WriteUnit(medi *description.Media, forma format.Format, u unit.Unit) {
sm := s.smedias[medi]
sf := sm.formats[forma]
s.mutex.RLock()
defer s.mutex.RUnlock()
sf.writeUnit(s, medi, data)
sf.writeUnit(s, medi, u)
}
// WriteRTPPacket writes a RTP packet.

View file

@ -8,15 +8,24 @@ import (
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/asyncwriter"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
)
func unitSize(u unit.Unit) uint64 {
n := uint64(0)
for _, pkt := range u.GetRTPPackets() {
n += uint64(pkt.MarshalSize())
}
return n
}
type streamFormat struct {
decodeErrLogger logger.Writer
proc formatprocessor.Processor
nonRTSPReaders map[interface{}]func(unit.Unit)
readers map[*asyncwriter.Writer]readerFunc
}
func newStreamFormat(
@ -33,50 +42,47 @@ func newStreamFormat(
sf := &streamFormat{
decodeErrLogger: decodeErrLogger,
proc: proc,
nonRTSPReaders: make(map[interface{}]func(unit.Unit)),
readers: make(map[*asyncwriter.Writer]readerFunc),
}
return sf, nil
}
func (sf *streamFormat) addReader(r interface{}, cb func(unit.Unit)) {
sf.nonRTSPReaders[r] = cb
func (sf *streamFormat) addReader(r *asyncwriter.Writer, cb readerFunc) {
sf.readers[r] = cb
}
func (sf *streamFormat) removeReader(r interface{}) {
delete(sf.nonRTSPReaders, r)
func (sf *streamFormat) removeReader(r *asyncwriter.Writer) {
delete(sf.readers, r)
}
func (sf *streamFormat) writeUnit(s *Stream, medi *description.Media, data unit.Unit) {
hasNonRTSPReaders := len(sf.nonRTSPReaders) > 0
func (sf *streamFormat) writeUnit(s *Stream, medi *description.Media, u unit.Unit) {
hasNonRTSPReaders := len(sf.readers) > 0
err := sf.proc.Process(data, hasNonRTSPReaders)
err := sf.proc.Process(u, hasNonRTSPReaders)
if err != nil {
sf.decodeErrLogger.Log(logger.Warn, err.Error())
return
}
n := uint64(0)
for _, pkt := range data.GetRTPPackets() {
n += uint64(pkt.MarshalSize())
}
atomic.AddUint64(s.bytesReceived, n)
atomic.AddUint64(s.bytesReceived, unitSize(u))
if s.rtspStream != nil {
for _, pkt := range data.GetRTPPackets() {
s.rtspStream.WritePacketRTPWithNTP(medi, pkt, data.GetNTP()) //nolint:errcheck
for _, pkt := range u.GetRTPPackets() {
s.rtspStream.WritePacketRTPWithNTP(medi, pkt, u.GetNTP()) //nolint:errcheck
}
}
if s.rtspsStream != nil {
for _, pkt := range data.GetRTPPackets() {
s.rtspsStream.WritePacketRTPWithNTP(medi, pkt, data.GetNTP()) //nolint:errcheck
for _, pkt := range u.GetRTPPackets() {
s.rtspsStream.WritePacketRTPWithNTP(medi, pkt, u.GetNTP()) //nolint:errcheck
}
}
// forward decoded frames to non-RTSP readers
for _, cb := range sf.nonRTSPReaders {
cb(data)
for writer, cb := range sf.readers {
writer.Push(func() error {
return cb(u)
})
}
}