Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/asticode/go-astits v1.14.0
github.com/bluenviron/gohlslib/v2 v2.2.5-0.20260117214804-b8c1ff42629d
github.com/bluenviron/gortmplib v0.2.0
github.com/bluenviron/gortsplib/v5 v5.2.2
github.com/bluenviron/gortsplib/v5 v5.2.3
github.com/bluenviron/mediacommon/v2 v2.6.0
github.com/datarhei/gosrt v0.9.0
github.com/fsnotify/fsnotify v1.9.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ github.com/bluenviron/gohlslib/v2 v2.2.5-0.20260117214804-b8c1ff42629d h1:Mm56CD
github.com/bluenviron/gohlslib/v2 v2.2.5-0.20260117214804-b8c1ff42629d/go.mod h1:iatp6XDIncpGlua8YU2wga01fU7pzp42nWG684GZhbM=
github.com/bluenviron/gortmplib v0.2.0 h1:j15eeHrgVh6Avg9oAx+r4w0HugTqrIqLBsYnhs3D1dE=
github.com/bluenviron/gortmplib v0.2.0/go.mod h1:yzobxBF8zusF2nKbEOF69zIIL429j0kaCWc/euNdvO4=
github.com/bluenviron/gortsplib/v5 v5.2.2 h1:5q2viB8PGxWOSXNhVvj8buyr1wighLbHqRZ0U7MLM3o=
github.com/bluenviron/gortsplib/v5 v5.2.2/go.mod h1:xkVBOAnR4fzaerPN650CBb7N+zUUsj7PI2HiY1TP7Co=
github.com/bluenviron/mediacommon/v2 v2.6.0 h1:wZAPXwv7V78Cx2x7cToYIHOLToHl6APcvHbdQT+gOkg=
github.com/bluenviron/mediacommon/v2 v2.6.0/go.mod h1:5V15TiOfeaNVmZPVuOqAwqQSWyvMV86/dijDKu5q9Zs=
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
Expand Down
28 changes: 28 additions & 0 deletions internal/conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ type Conf struct {
PlaybackAllowOrigins []string `json:"playbackAllowOrigins"`
PlaybackTrustedProxies IPNetworks `json:"playbackTrustedProxies"`

// RTSP Source (Streams IN)
UDPClientPortRange *[]uint16 `json:"sourceUDPClientPortRange,omitempty"`

// RTSP server
RTSP bool `json:"rtsp"`
RTSPDisable *bool `json:"rtspDisable,omitempty"` // deprecated
Expand Down Expand Up @@ -459,6 +462,9 @@ func (conf *Conf) setDefaults() {
conf.PlaybackServerCert = "server.crt"
conf.PlaybackAllowOrigins = []string{"*"}

// RTSP Client
conf.UDPClientPortRange = &([]uint16{10000, 65535})

// RTSP server
conf.RTSP = true
conf.RTSPTransports = RTSPTransports{
Expand Down Expand Up @@ -769,6 +775,28 @@ func (conf *Conf) Validate(l logger.Writer) error {
conf.PlaybackAllowOrigins = []string{*conf.PlaybackAllowOrigin}
}

// RTSP Client

if len(*conf.UDPClientPortRange) != 2 {
return fmt.Errorf("parameter 'udpClientPortRange' does not have two port range limits - min and max")
}

udpCportmin := (*conf.UDPClientPortRange)[0]
udpCportmax := (*conf.UDPClientPortRange)[1]

if udpCportmin < 10000 || udpCportmax > 65534 {
return fmt.Errorf("'udpClientPortRange' lower bound should not be < 10000 and upper bound should not be > 65534")
}

if (udpCportmax%2 != 0) || (udpCportmin%2 != 0) {
return fmt.Errorf("'udpClientPortRange' lower bound and upper bound should be even numbers")
}

if udpCportmax-udpCportmin < 10 {
return fmt.Errorf("'udpClientPortRange' range should be at least 10 ports")
}

// RTSP server
// Playback

if conf.Playback {
Expand Down
50 changes: 50 additions & 0 deletions internal/conf/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,56 @@ func loadEnvInternal(env map[string]string, prefix string, prv reflect.Value) er
}
return nil

case rt.Elem() == reflect.TypeOf(uint(0)):
if ev, ok := env[prefix]; ok {
if ev == "" {
prv.Elem().Set(reflect.MakeSlice(prv.Elem().Type(), 0, 0))
} else {
if prv.IsNil() {
prv.Set(reflect.New(rt))
}

raw := strings.Split(ev, ",")
vals := make([]uint, len(raw))

for i, v := range raw {
tmp, err := strconv.ParseUint(v, 10, 32)
if err != nil {
return err
}
vals[i] = uint(tmp)
}

prv.Elem().Set(reflect.ValueOf(vals))
}
}
return nil

case rt.Elem() == reflect.TypeOf(uint16(0)):
if ev, ok := env[prefix]; ok {
if ev == "" {
prv.Elem().Set(reflect.MakeSlice(prv.Elem().Type(), 0, 0))
} else {
if prv.IsNil() {
prv.Set(reflect.New(rt))
}

raw := strings.Split(ev, ",")
vals := make([]uint16, len(raw))

for i, v := range raw {
tmp, err := strconv.ParseUint(v, 10, 16)
if err != nil {
return err
}
vals[i] = uint16(tmp)
}

prv.Elem().Set(reflect.ValueOf(vals))
}
}
return nil

case rt.Elem().Kind() == reflect.Struct:
if ev, ok := env[prefix]; ok && ev == "" { // special case: empty list
prv.Elem().Set(reflect.MakeSlice(prv.Elem().Type(), 0, 0))
Expand Down
27 changes: 15 additions & 12 deletions internal/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,18 +424,19 @@ func (p *Core) createResources(initial bool) error {
rtpMaxPayloadSize := getRTPMaxPayloadSize(p.conf.UDPMaxPayloadSize, p.conf.RTSPEncryption)

p.pathManager = &pathManager{
logLevel: p.conf.LogLevel,
authManager: p.authManager,
rtspAddress: p.conf.RTSPAddress,
readTimeout: p.conf.ReadTimeout,
writeTimeout: p.conf.WriteTimeout,
writeQueueSize: p.conf.WriteQueueSize,
udpReadBufferSize: p.conf.UDPReadBufferSize,
rtpMaxPayloadSize: rtpMaxPayloadSize,
pathConfs: p.conf.Paths,
externalCmdPool: p.externalCmdPool,
metrics: p.metrics,
parent: p,
logLevel: p.conf.LogLevel,
authManager: p.authManager,
rtspAddress: p.conf.RTSPAddress,
readTimeout: p.conf.ReadTimeout,
writeTimeout: p.conf.WriteTimeout,
writeQueueSize: p.conf.WriteQueueSize,
udpReadBufferSize: p.conf.UDPReadBufferSize,
udpClientPortRange: *p.conf.UDPClientPortRange,
rtpMaxPayloadSize: rtpMaxPayloadSize,
pathConfs: p.conf.Paths,
externalCmdPool: p.externalCmdPool,
metrics: p.metrics,
parent: p,
}
p.pathManager.initialize()
}
Expand Down Expand Up @@ -786,6 +787,8 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
newConf.WriteTimeout != p.conf.WriteTimeout ||
newConf.WriteQueueSize != p.conf.WriteQueueSize ||
newConf.UDPReadBufferSize != p.conf.UDPReadBufferSize ||
(*newConf.UDPClientPortRange)[0] != (*p.conf.UDPClientPortRange)[0] ||
(*newConf.UDPClientPortRange)[1] != (*p.conf.UDPClientPortRange)[1] ||
newConf.UDPMaxPayloadSize != p.conf.UDPMaxPayloadSize ||
newConf.RTSPEncryption != p.conf.RTSPEncryption ||
closeMetrics ||
Expand Down
50 changes: 26 additions & 24 deletions internal/core/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"sync"
"time"

"github.com/bluenviron/gortsplib/v5/pkg/description"

Check failure on line 11 in internal/core/path.go

View workflow job for this annotation

GitHub Actions / test_e2e

missing go.sum entry for module providing package github.com/bluenviron/gortsplib/v5/pkg/description (imported by github.com/bluenviron/mediamtx/internal/core); to add:

"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/defs"
Expand Down Expand Up @@ -64,20 +64,21 @@
}

type path struct {
parentCtx context.Context
logLevel conf.LogLevel
rtspAddress string
readTimeout conf.Duration
writeTimeout conf.Duration
writeQueueSize int
udpReadBufferSize uint
rtpMaxPayloadSize int
conf *conf.Path
name string
matches []string
wg *sync.WaitGroup
externalCmdPool *externalcmd.Pool
parent pathParent
parentCtx context.Context
logLevel conf.LogLevel
rtspAddress string
readTimeout conf.Duration
writeTimeout conf.Duration
writeQueueSize int
udpReadBufferSize uint
udpClientPortRange []uint16
rtpMaxPayloadSize int
conf *conf.Path
name string
matches []string
wg *sync.WaitGroup
externalCmdPool *externalcmd.Pool
parent pathParent

ctx context.Context
ctxCancel func()
Expand Down Expand Up @@ -170,16 +171,17 @@
pa.source = &sourceRedirect{}
} else if pa.conf.HasStaticSource() {
pa.source = &staticsources.Handler{
Conf: pa.conf,
LogLevel: pa.logLevel,
ReadTimeout: pa.readTimeout,
WriteTimeout: pa.writeTimeout,
WriteQueueSize: pa.writeQueueSize,
UDPReadBufferSize: pa.udpReadBufferSize,
RTPMaxPayloadSize: pa.rtpMaxPayloadSize,
Matches: pa.matches,
PathManager: pa.parent,
Parent: pa,
Conf: pa.conf,
LogLevel: pa.logLevel,
ReadTimeout: pa.readTimeout,
WriteTimeout: pa.writeTimeout,
WriteQueueSize: pa.writeQueueSize,
UDPReadBufferSize: pa.udpReadBufferSize,
UDPClientPortRange: pa.udpClientPortRange,
RTPMaxPayloadSize: pa.rtpMaxPayloadSize,
Matches: pa.matches,
PathManager: pa.parent,
Parent: pa,
}
pa.source.(*staticsources.Handler).Initialize()

Expand Down
54 changes: 28 additions & 26 deletions internal/core/path_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,19 @@ type pathManagerParent interface {
}

type pathManager struct {
logLevel conf.LogLevel
authManager *auth.Manager
rtspAddress string
readTimeout conf.Duration
writeTimeout conf.Duration
writeQueueSize int
udpReadBufferSize uint
rtpMaxPayloadSize int
pathConfs map[string]*conf.Path
externalCmdPool *externalcmd.Pool
metrics *metrics.Metrics
parent pathManagerParent
logLevel conf.LogLevel
authManager *auth.Manager
rtspAddress string
readTimeout conf.Duration
writeTimeout conf.Duration
writeQueueSize int
udpReadBufferSize uint
udpClientPortRange []uint16
rtpMaxPayloadSize int
pathConfs map[string]*conf.Path
externalCmdPool *externalcmd.Pool
metrics *metrics.Metrics
parent pathManagerParent

ctx context.Context
ctxCancel func()
Expand Down Expand Up @@ -434,20 +435,21 @@ func (pm *pathManager) createPath(
matches []string,
) {
pa := &path{
parentCtx: pm.ctx,
logLevel: pm.logLevel,
rtspAddress: pm.rtspAddress,
readTimeout: pm.readTimeout,
writeTimeout: pm.writeTimeout,
writeQueueSize: pm.writeQueueSize,
udpReadBufferSize: pm.udpReadBufferSize,
rtpMaxPayloadSize: pm.rtpMaxPayloadSize,
conf: pathConf,
name: name,
matches: matches,
wg: &pm.wg,
externalCmdPool: pm.externalCmdPool,
parent: pm,
parentCtx: pm.ctx,
logLevel: pm.logLevel,
rtspAddress: pm.rtspAddress,
readTimeout: pm.readTimeout,
writeTimeout: pm.writeTimeout,
writeQueueSize: pm.writeQueueSize,
udpReadBufferSize: pm.udpReadBufferSize,
udpClientPortRange: pm.udpClientPortRange,
rtpMaxPayloadSize: pm.rtpMaxPayloadSize,
conf: pathConf,
name: name,
matches: matches,
wg: &pm.wg,
externalCmdPool: pm.externalCmdPool,
parent: pm,
}
pa.initialize()

Expand Down
32 changes: 17 additions & 15 deletions internal/staticsources/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,17 @@ type handlerParent interface {

// Handler is a static source handler.
type Handler struct {
Conf *conf.Path
LogLevel conf.LogLevel
ReadTimeout conf.Duration
WriteTimeout conf.Duration
WriteQueueSize int
UDPReadBufferSize uint
RTPMaxPayloadSize int
Matches []string
PathManager handlerPathManager
Parent handlerParent
Conf *conf.Path
LogLevel conf.LogLevel
ReadTimeout conf.Duration
WriteTimeout conf.Duration
WriteQueueSize int
UDPReadBufferSize uint
UDPClientPortRange []uint16
RTPMaxPayloadSize int
Matches []string
PathManager handlerPathManager
Parent handlerParent

ctx context.Context
ctxCancel func()
Expand Down Expand Up @@ -102,11 +103,12 @@ func (s *Handler) Initialize() {
strings.HasPrefix(s.Conf.Source, "rtsp+ws://") ||
strings.HasPrefix(s.Conf.Source, "rtsps+ws://"):
s.instance = &ssrtsp.Source{
ReadTimeout: s.ReadTimeout,
WriteTimeout: s.WriteTimeout,
WriteQueueSize: s.WriteQueueSize,
UDPReadBufferSize: s.UDPReadBufferSize,
Parent: s,
ReadTimeout: s.ReadTimeout,
WriteTimeout: s.WriteTimeout,
WriteQueueSize: s.WriteQueueSize,
UDPReadBufferSize: s.UDPReadBufferSize,
UDPClientPortRange: s.UDPClientPortRange,
Parent: s,
}

case strings.HasPrefix(s.Conf.Source, "rtmp://") ||
Expand Down
Loading
Loading