Skip to content

Commit

Permalink
allow using 'fallback' with static sources (bluenviron#2606) (bluenvi…
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 authored Nov 16, 2023
1 parent 4fa6c16 commit c3d9be3
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 67 deletions.
4 changes: 2 additions & 2 deletions apidocs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ components:
type: integer
srtReadPassphrase:
type: string
fallback:
type: string

# Record
record:
Expand Down Expand Up @@ -246,8 +248,6 @@ components:
# Publisher source
overridePublisher:
type: boolean
fallback:
type: string
srtPublishPassphrase:
type: string

Expand Down
32 changes: 14 additions & 18 deletions internal/conf/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type Path struct {
SourceOnDemandCloseAfter StringDuration `json:"sourceOnDemandCloseAfter"`
MaxReaders int `json:"maxReaders"`
SRTReadPassphrase string `json:"srtReadPassphrase"`
Fallback string `json:"fallback"`

// Record
Record bool `json:"record"`
Expand All @@ -80,7 +81,6 @@ type Path struct {
// Publisher source
OverridePublisher bool `json:"overridePublisher"`
DisablePublisherOverride *bool `json:"disablePublisherOverride,omitempty"` // deprecated
Fallback string `json:"fallback"`
SRTPublishPassphrase string `json:"srtPublishPassphrase"`

// RTSP source
Expand Down Expand Up @@ -346,6 +346,19 @@ func (pconf *Path) check(conf *Conf, name string) error {
return fmt.Errorf("invalid 'readRTPassphrase': %v", err)
}
}
if pconf.Fallback != "" {
if strings.HasPrefix(pconf.Fallback, "/") {
err := IsValidPathName(pconf.Fallback[1:])
if err != nil {
return fmt.Errorf("'%s': %s", pconf.Fallback, err)
}
} else {
_, err := base.ParseURL(pconf.Fallback)
if err != nil {
return fmt.Errorf("'%s' is not a valid RTSP URL", pconf.Fallback)
}
}
}

// Authentication

Expand Down Expand Up @@ -387,23 +400,6 @@ func (pconf *Path) check(conf *Conf, name string) error {
if pconf.DisablePublisherOverride != nil {
pconf.OverridePublisher = !*pconf.DisablePublisherOverride
}
if pconf.Fallback != "" {
if pconf.Source != "publisher" {
return fmt.Errorf("'fallback' can only be used when source is 'publisher'")
}

if strings.HasPrefix(pconf.Fallback, "/") {
err := IsValidPathName(pconf.Fallback[1:])
if err != nil {
return fmt.Errorf("'%s': %s", pconf.Fallback, err)
}
} else {
_, err := base.ParseURL(pconf.Fallback)
if err != nil {
return fmt.Errorf("'%s' is not a valid RTSP URL", pconf.Fallback)
}
}
}
if pconf.SRTPublishPassphrase != "" {
if pconf.Source != "publisher" {
return fmt.Errorf("'srtPublishPassphase' can only be used when source is 'publisher'")
Expand Down
55 changes: 55 additions & 0 deletions internal/core/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,58 @@ func TestPathRecord(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 2, len(files))
}

func TestPathFallback(t *testing.T) {
for _, ca := range []string{
"absolute",
"relative",
"source",
} {
t.Run(ca, func(t *testing.T) {
var conf string

switch ca {
case "absolute":
conf = "paths:\n" +
" path1:\n" +
" fallback: rtsp://localhost:8554/path2\n" +
" path2:\n"

case "relative":
conf = "paths:\n" +
" path1:\n" +
" fallback: /path2\n" +
" path2:\n"

case "source":
conf = "paths:\n" +
" path1:\n" +
" fallback: /path2\n" +
" source: rtsp://localhost:3333/nonexistent\n" +
" path2:\n"
}

p1, ok := newInstance(conf)
require.Equal(t, true, ok)
defer p1.Close()

source := gortsplib.Client{}
err := source.StartRecording("rtsp://localhost:8554/path2",
&description.Session{Medias: []*description.Media{testMediaH264}})
require.NoError(t, err)
defer source.Close()

u, err := base.ParseURL("rtsp://localhost:8554/path1")
require.NoError(t, err)

dest := gortsplib.Client{}
err = dest.Start(u.Scheme, u.Host)
require.NoError(t, err)
defer dest.Close()

desc, _, err := dest.Describe(u)
require.NoError(t, err)
require.Equal(t, 1, len(desc.Medias))
})
}
}
44 changes: 0 additions & 44 deletions internal/core/rtsp_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,47 +348,3 @@ func TestRTSPServerPublisherOverride(t *testing.T) {
})
}
}

func TestRTSPServerFallback(t *testing.T) {
for _, ca := range []string{
"absolute",
"relative",
} {
t.Run(ca, func(t *testing.T) {
val := func() string {
if ca == "absolute" {
return "rtsp://localhost:8554/path2"
}
return "/path2"
}()

p1, ok := newInstance("rtmp: no\n" +
"hls: no\n" +
"webrtc: no\n" +
"paths:\n" +
" path1:\n" +
" fallback: " + val + "\n" +
" path2:\n")
require.Equal(t, true, ok)
defer p1.Close()

source := gortsplib.Client{}
err := source.StartRecording("rtsp://localhost:8554/path2",
&description.Session{Medias: []*description.Media{testMediaH264}})
require.NoError(t, err)
defer source.Close()

u, err := base.ParseURL("rtsp://localhost:8554/path1")
require.NoError(t, err)

dest := gortsplib.Client{}
err = dest.Start(u.Scheme, u.Host)
require.NoError(t, err)
defer dest.Close()

desc, _, err := dest.Describe(u)
require.NoError(t, err)
require.Equal(t, 1, len(desc.Medias))
})
}
}
6 changes: 3 additions & 3 deletions mediamtx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ pathDefaults:
maxReaders: 0
# SRT encryption passphrase require to read from this path
srtReadPassphrase:
# If the stream is not available, redirect readers to this path.
# It can be can be a relative path (i.e. /otherstream) or an absolute RTSP URL.
fallback:

###############################################
# Default path settings -> Recording
Expand Down Expand Up @@ -335,9 +338,6 @@ pathDefaults:

# Allow another client to disconnect the current publisher and publish in its place.
overridePublisher: yes
# If no one is publishing, redirect readers to this path.
# It can be can be a relative path (i.e. /otherstream) or an absolute RTSP URL.
fallback:
# SRT encryption passphrase required to publish to this path
srtPublishPassphrase:

Expand Down

0 comments on commit c3d9be3

Please sign in to comment.