support automatic protocol selection when proxying rtsp
This commit is contained in:
parent
eaf115f604
commit
a9dee11496
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ go 1.15
|
|||
require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
|
||||
github.com/aler9/gortsplib v0.0.0-20201120083135-e66459731e97
|
||||
github.com/aler9/gortsplib v0.0.0-20201121121323-a6d0fc140b6e
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
|
|
4
go.sum
4
go.sum
|
@ -2,8 +2,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo
|
|||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/aler9/gortsplib v0.0.0-20201120083135-e66459731e97 h1:sefesnUXzUHF4fhS+rnpON5MpMOjka5YFka9P5qiS5s=
|
||||
github.com/aler9/gortsplib v0.0.0-20201120083135-e66459731e97/go.mod h1:6yKsTNIrCapRz90WHQtyFV/rKK0TT+QapxUXNqSJi9M=
|
||||
github.com/aler9/gortsplib v0.0.0-20201121121323-a6d0fc140b6e h1:4BltbY0GVgVQntou5KQGpE0fL33tRq5o1zPY5pbyrlU=
|
||||
github.com/aler9/gortsplib v0.0.0-20201121121323-a6d0fc140b6e/go.mod h1:6yKsTNIrCapRz90WHQtyFV/rKK0TT+QapxUXNqSJi9M=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
|
|
@ -205,12 +205,12 @@ func (c *Client) run() {
|
|||
defer c.wg.Done()
|
||||
defer c.log("disconnected")
|
||||
|
||||
var onConnectCmd *externalcmd.ExternalCmd
|
||||
if c.runOnConnect != "" {
|
||||
onConnectCmd = externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{
|
||||
onConnectCmd := externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{
|
||||
Path: "",
|
||||
Port: strconv.FormatInt(int64(c.rtspPort), 10),
|
||||
})
|
||||
defer onConnectCmd.Close()
|
||||
}
|
||||
|
||||
for {
|
||||
|
@ -223,10 +223,6 @@ func (c *Client) run() {
|
|||
c.path.OnClientRemove(c)
|
||||
c.path = nil
|
||||
}
|
||||
|
||||
if onConnectCmd != nil {
|
||||
onConnectCmd.Close()
|
||||
}
|
||||
}
|
||||
|
||||
type errAuthNotCritical struct {
|
||||
|
|
|
@ -18,33 +18,33 @@ const userPassSupportedChars = "A-Z,0-9,!,$,(,),*,+,.,;,<,=,>,[,],^,_,-,{,}"
|
|||
|
||||
// PathConf is a path configuration.
|
||||
type PathConf struct {
|
||||
Regexp *regexp.Regexp `yaml:"-" json:"-"`
|
||||
Source string `yaml:"source"`
|
||||
SourceProtocol string `yaml:"sourceProtocol"`
|
||||
SourceProtocolParsed gortsplib.StreamProtocol `yaml:"-" json:"-"`
|
||||
SourceOnDemand bool `yaml:"sourceOnDemand"`
|
||||
SourceOnDemandStartTimeout time.Duration `yaml:"sourceOnDemandStartTimeout"`
|
||||
SourceOnDemandCloseAfter time.Duration `yaml:"sourceOnDemandCloseAfter"`
|
||||
SourceRedirect string `yaml:"sourceRedirect"`
|
||||
Fallback string `yaml:"fallback"`
|
||||
RunOnInit string `yaml:"runOnInit"`
|
||||
RunOnInitRestart bool `yaml:"runOnInitRestart"`
|
||||
RunOnDemand string `yaml:"runOnDemand"`
|
||||
RunOnDemandRestart bool `yaml:"runOnDemandRestart"`
|
||||
RunOnDemandStartTimeout time.Duration `yaml:"runOnDemandStartTimeout"`
|
||||
RunOnDemandCloseAfter time.Duration `yaml:"runOnDemandCloseAfter"`
|
||||
RunOnPublish string `yaml:"runOnPublish"`
|
||||
RunOnPublishRestart bool `yaml:"runOnPublishRestart"`
|
||||
RunOnRead string `yaml:"runOnRead"`
|
||||
RunOnReadRestart bool `yaml:"runOnReadRestart"`
|
||||
PublishUser string `yaml:"publishUser"`
|
||||
PublishPass string `yaml:"publishPass"`
|
||||
PublishIps []string `yaml:"publishIps"`
|
||||
PublishIpsParsed []interface{} `yaml:"-" json:"-"`
|
||||
ReadUser string `yaml:"readUser"`
|
||||
ReadPass string `yaml:"readPass"`
|
||||
ReadIps []string `yaml:"readIps"`
|
||||
ReadIpsParsed []interface{} `yaml:"-" json:"-"`
|
||||
Regexp *regexp.Regexp `yaml:"-" json:"-"`
|
||||
Source string `yaml:"source"`
|
||||
SourceProtocol string `yaml:"sourceProtocol"`
|
||||
SourceProtocolParsed *gortsplib.StreamProtocol `yaml:"-" json:"-"`
|
||||
SourceOnDemand bool `yaml:"sourceOnDemand"`
|
||||
SourceOnDemandStartTimeout time.Duration `yaml:"sourceOnDemandStartTimeout"`
|
||||
SourceOnDemandCloseAfter time.Duration `yaml:"sourceOnDemandCloseAfter"`
|
||||
SourceRedirect string `yaml:"sourceRedirect"`
|
||||
Fallback string `yaml:"fallback"`
|
||||
RunOnInit string `yaml:"runOnInit"`
|
||||
RunOnInitRestart bool `yaml:"runOnInitRestart"`
|
||||
RunOnDemand string `yaml:"runOnDemand"`
|
||||
RunOnDemandRestart bool `yaml:"runOnDemandRestart"`
|
||||
RunOnDemandStartTimeout time.Duration `yaml:"runOnDemandStartTimeout"`
|
||||
RunOnDemandCloseAfter time.Duration `yaml:"runOnDemandCloseAfter"`
|
||||
RunOnPublish string `yaml:"runOnPublish"`
|
||||
RunOnPublishRestart bool `yaml:"runOnPublishRestart"`
|
||||
RunOnRead string `yaml:"runOnRead"`
|
||||
RunOnReadRestart bool `yaml:"runOnReadRestart"`
|
||||
PublishUser string `yaml:"publishUser"`
|
||||
PublishPass string `yaml:"publishPass"`
|
||||
PublishIps []string `yaml:"publishIps"`
|
||||
PublishIpsParsed []interface{} `yaml:"-" json:"-"`
|
||||
ReadUser string `yaml:"readUser"`
|
||||
ReadPass string `yaml:"readPass"`
|
||||
ReadIps []string `yaml:"readIps"`
|
||||
ReadIpsParsed []interface{} `yaml:"-" json:"-"`
|
||||
}
|
||||
|
||||
func (pconf *PathConf) fillAndCheck(name string) error {
|
||||
|
@ -94,15 +94,19 @@ func (pconf *PathConf) fillAndCheck(name string) error {
|
|||
}
|
||||
|
||||
if pconf.SourceProtocol == "" {
|
||||
pconf.SourceProtocol = "udp"
|
||||
pconf.SourceProtocol = "automatic"
|
||||
}
|
||||
|
||||
switch pconf.SourceProtocol {
|
||||
case "udp":
|
||||
pconf.SourceProtocolParsed = gortsplib.StreamProtocolUDP
|
||||
v := gortsplib.StreamProtocolUDP
|
||||
pconf.SourceProtocolParsed = &v
|
||||
|
||||
case "tcp":
|
||||
pconf.SourceProtocolParsed = gortsplib.StreamProtocolTCP
|
||||
v := gortsplib.StreamProtocolTCP
|
||||
pconf.SourceProtocolParsed = &v
|
||||
|
||||
case "automatic":
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unsupported protocol '%s'", pconf.SourceProtocol)
|
||||
|
|
|
@ -155,7 +155,6 @@ type Path struct {
|
|||
sourceTrackCount int
|
||||
sourceSdp []byte
|
||||
readers *readersMap
|
||||
onInitCmd *externalcmd.ExternalCmd
|
||||
onDemandCmd *externalcmd.ExternalCmd
|
||||
describeTimer *time.Timer
|
||||
sourceCloseTimer *time.Timer
|
||||
|
@ -245,9 +244,10 @@ func (pa *Path) run() {
|
|||
pa.startExternalSource()
|
||||
}
|
||||
|
||||
var onInitCmd *externalcmd.ExternalCmd
|
||||
if pa.conf.RunOnInit != "" {
|
||||
pa.Log("on init command started")
|
||||
pa.onInitCmd = externalcmd.New(pa.conf.RunOnInit, pa.conf.RunOnInitRestart, externalcmd.Environment{
|
||||
onInitCmd = externalcmd.New(pa.conf.RunOnInit, pa.conf.RunOnInitRestart, externalcmd.Environment{
|
||||
Path: pa.name,
|
||||
Port: strconv.FormatInt(int64(pa.rtspPort), 10),
|
||||
})
|
||||
|
@ -363,9 +363,9 @@ outer:
|
|||
pa.runOnDemandCloseTimer.Stop()
|
||||
pa.closeTimer.Stop()
|
||||
|
||||
if pa.onInitCmd != nil {
|
||||
if onInitCmd != nil {
|
||||
pa.Log("on init command stopped")
|
||||
pa.onInitCmd.Close()
|
||||
onInitCmd.Close()
|
||||
}
|
||||
|
||||
if source, ok := pa.source.(sourceExternal); ok {
|
||||
|
|
|
@ -25,7 +25,7 @@ type Parent interface {
|
|||
// Source is a RTSP source.
|
||||
type Source struct {
|
||||
ur string
|
||||
proto gortsplib.StreamProtocol
|
||||
proto *gortsplib.StreamProtocol
|
||||
readTimeout time.Duration
|
||||
writeTimeout time.Duration
|
||||
wg *sync.WaitGroup
|
||||
|
@ -41,7 +41,7 @@ type Source struct {
|
|||
|
||||
// New allocates a Source.
|
||||
func New(ur string,
|
||||
proto gortsplib.StreamProtocol,
|
||||
proto *gortsplib.StreamProtocol,
|
||||
readTimeout time.Duration,
|
||||
writeTimeout time.Duration,
|
||||
wg *sync.WaitGroup,
|
||||
|
|
13
main_test.go
13
main_test.go
|
@ -187,7 +187,7 @@ func TestEnvironment(t *testing.T) {
|
|||
require.Equal(t, &conf.PathConf{
|
||||
Regexp: regexp.MustCompile("^.*$"),
|
||||
Source: "record",
|
||||
SourceProtocol: "udp",
|
||||
SourceProtocol: "automatic",
|
||||
SourceOnDemandStartTimeout: 10 * time.Second,
|
||||
SourceOnDemandCloseAfter: 10 * time.Second,
|
||||
ReadUser: "testuser",
|
||||
|
@ -199,9 +199,12 @@ func TestEnvironment(t *testing.T) {
|
|||
pa, ok = p.conf.Paths["cam1"]
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, &conf.PathConf{
|
||||
Source: "rtsp://testing",
|
||||
SourceProtocol: "tcp",
|
||||
SourceProtocolParsed: gortsplib.StreamProtocolTCP,
|
||||
Source: "rtsp://testing",
|
||||
SourceProtocol: "tcp",
|
||||
SourceProtocolParsed: func() *gortsplib.StreamProtocol {
|
||||
v := gortsplib.StreamProtocolTCP
|
||||
return &v
|
||||
}(),
|
||||
SourceOnDemand: true,
|
||||
SourceOnDemandStartTimeout: 10 * time.Second,
|
||||
SourceOnDemandCloseAfter: 10 * time.Second,
|
||||
|
@ -222,7 +225,7 @@ func TestEnvironmentNoFile(t *testing.T) {
|
|||
require.Equal(t, true, ok)
|
||||
require.Equal(t, &conf.PathConf{
|
||||
Source: "rtsp://testing",
|
||||
SourceProtocol: "udp",
|
||||
SourceProtocol: "automatic",
|
||||
SourceOnDemandStartTimeout: 10 * time.Second,
|
||||
SourceOnDemandCloseAfter: 10 * time.Second,
|
||||
RunOnDemandStartTimeout: 10 * time.Second,
|
||||
|
|
|
@ -48,8 +48,8 @@ paths:
|
|||
source: record
|
||||
|
||||
# if the source is an RTSP url, this is the protocol that will be used to
|
||||
# pull the stream.
|
||||
sourceProtocol: udp
|
||||
# pull the stream. available options are "automatic", "udp", "tcp".
|
||||
sourceProtocol: automatic
|
||||
# if the source is an RTSP or RTMP url, it will be pulled only when at least
|
||||
# one reader is connected, saving bandwidth.
|
||||
sourceOnDemand: no
|
||||
|
|
Loading…
Reference in New Issue