support automatic protocol selection when proxying rtsp

This commit is contained in:
aler9 2020-11-21 13:34:27 +01:00
parent eaf115f604
commit a9dee11496
8 changed files with 55 additions and 52 deletions

2
go.mod
View File

@ -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
View File

@ -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=

View File

@ -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 {

View File

@ -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)

View File

@ -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 {

View File

@ -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,

View File

@ -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,

View File

@ -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