mediamtx/internal/stream/stream.go

141 lines
3.0 KiB
Go
Raw Normal View History

// Package stream contains the Stream object.
package stream
import (
2023-08-26 16:54:28 +00:00
"sync"
"time"
2023-08-26 16:54:28 +00:00
"github.com/bluenviron/gortsplib/v4"
"github.com/bluenviron/gortsplib/v4/pkg/description"
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
)
// Stream is a media stream.
// It stores tracks, readers and allow to write data to readers.
type Stream struct {
2023-08-26 16:54:28 +00:00
desc *description.Session
bytesReceived *uint64
2023-08-26 16:54:28 +00:00
smedias map[*description.Media]*streamMedia
mutex sync.RWMutex
rtspStream *gortsplib.ServerStream
rtspsStream *gortsplib.ServerStream
}
// New allocates a Stream.
func New(
udpMaxPayloadSize int,
2023-08-26 16:54:28 +00:00
desc *description.Session,
generateRTPPackets bool,
bytesReceived *uint64,
source logger.Writer,
) (*Stream, error) {
s := &Stream{
bytesReceived: bytesReceived,
2023-08-26 16:54:28 +00:00
desc: desc,
}
2023-08-26 16:54:28 +00:00
s.smedias = make(map[*description.Media]*streamMedia)
2023-08-26 16:54:28 +00:00
for _, media := range desc.Medias {
var err error
s.smedias[media], err = newStreamMedia(udpMaxPayloadSize, media, generateRTPPackets, source)
if err != nil {
return nil, err
}
}
return s, nil
}
// Close closes all resources of the stream.
func (s *Stream) Close() {
2023-08-26 16:54:28 +00:00
if s.rtspStream != nil {
s.rtspStream.Close()
}
if s.rtspsStream != nil {
s.rtspsStream.Close()
}
}
2023-08-26 16:54:28 +00:00
// Desc returns description of the stream.
func (s *Stream) Desc() *description.Session {
return s.desc
}
// RTSPStream returns the RTSP stream.
2023-08-26 16:54:28 +00:00
func (s *Stream) RTSPStream(server *gortsplib.Server) *gortsplib.ServerStream {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.rtspStream == nil {
s.rtspStream = gortsplib.NewServerStream(server, s.desc)
}
return s.rtspStream
}
2023-08-26 16:54:28 +00:00
// RTSPSStream returns the RTSPS stream.
func (s *Stream) RTSPSStream(server *gortsplib.Server) *gortsplib.ServerStream {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.rtspsStream == nil {
s.rtspsStream = gortsplib.NewServerStream(server, s.desc)
}
return s.rtspsStream
}
// AddReader adds a reader.
2023-08-26 16:54:28 +00:00
func (s *Stream) AddReader(r interface{}, medi *description.Media, forma format.Format, cb func(unit.Unit)) {
s.mutex.Lock()
defer s.mutex.Unlock()
sm := s.smedias[medi]
sf := sm.formats[forma]
sf.addReader(r, cb)
}
// RemoveReader removes a reader.
func (s *Stream) RemoveReader(r interface{}) {
2023-08-26 16:54:28 +00:00
s.mutex.Lock()
defer s.mutex.Unlock()
for _, sm := range s.smedias {
for _, sf := range sm.formats {
sf.removeReader(r)
}
}
}
// WriteUnit writes a Unit.
2023-08-26 16:54:28 +00:00
func (s *Stream) WriteUnit(medi *description.Media, forma format.Format, data unit.Unit) {
sm := s.smedias[medi]
sf := sm.formats[forma]
2023-08-26 16:54:28 +00:00
s.mutex.RLock()
defer s.mutex.RUnlock()
sf.writeUnit(s, medi, data)
2021-11-12 21:29:56 +00:00
}
// WriteRTPPacket writes a RTP packet.
2023-08-26 16:54:28 +00:00
func (s *Stream) WriteRTPPacket(
medi *description.Media,
forma format.Format,
pkt *rtp.Packet,
ntp time.Time,
pts time.Duration,
) {
sm := s.smedias[medi]
sf := sm.formats[forma]
2023-08-26 16:54:28 +00:00
s.mutex.RLock()
defer s.mutex.RUnlock()
sf.writeRTPPacket(s, medi, pkt, ntp, pts)
}