Browse Source

new environment variable RTSP_PORT

pull/169/head
aler9 5 years ago
parent
commit
bbc2401ac2
  1. 10
      Makefile
  2. 8
      README.md
  3. 44
      client/client.go
  4. 17
      clientman/clientman.go
  5. 24
      externalcmd/externalcmd.go
  6. 13
      main.go
  7. 6
      main_test.go
  8. 16
      path/path.go
  9. 18
      pathman/pathman.go
  10. 5
      rtsp-simple-server.yml

10
Makefile

@ -80,19 +80,19 @@ define CONFIG_RUN @@ -80,19 +80,19 @@ define CONFIG_RUN
paths:
all:
# runOnPublish: ffmpeg -i rtsp://localhost:8554/$$RTSP_PATH -c copy -f mpegts myfile_$$RTSP_PATH.ts
# runOnPublish: ffmpeg -i rtsp://localhost:$$RTSP_PORT/$$RTSP_PATH -c copy -f mpegts myfile_$$RTSP_PATH.ts
# readUser: test
# readPass: tast
# runOnDemand: ffmpeg -re -stream_loop -1 -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:8554/$$RTSP_PATH
# runOnDemand: ffmpeg -re -stream_loop -1 -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:$$RTSP_PORT/$$RTSP_PATH
# proxied:
# source: rtsp://192.168.2.198:8554/stream
# source: rtsp://192.168.2.198:554/stream
# sourceProtocol: tcp
# sourceOnDemand: yes
# runOnDemand: ffmpeg -i rtsp://192.168.2.198:8554/stream -c copy -f rtsp rtsp://localhost:8554/proxied2
# runOnDemand: ffmpeg -i rtsp://192.168.2.198:554/stream -c copy -f rtsp rtsp://localhost:$$RTSP_PORT/proxied2
# original:
# runOnPublish: ffmpeg -i rtsp://localhost:8554/original -b:a 64k -c:v libx264 -preset ultrafast -b:v 500k -max_muxing_queue_size 1024 -f rtsp rtsp://localhost:8554/compressed
# runOnPublish: ffmpeg -i rtsp://localhost:554/original -b:a 64k -c:v libx264 -preset ultrafast -b:v 500k -max_muxing_queue_size 1024 -f rtsp rtsp://localhost:8554/compressed
endef
export CONFIG_RUN

8
README.md

@ -108,7 +108,7 @@ Edit `rtsp-simple-server.yml` and replace everything inside section `paths` with @@ -108,7 +108,7 @@ Edit `rtsp-simple-server.yml` and replace everything inside section `paths` with
```yaml
paths:
cam:
runOnInit: ffmpeg -f v4l2 -i /dev/video0 -f rtsp rtsp://localhost:8554/$RTSP_PATH
runOnInit: ffmpeg -f v4l2 -i /dev/video0 -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH
runOnInitRestart: yes
```
@ -128,7 +128,7 @@ Then edit `rtsp-simple-server.yml` and replace everything inside section `paths` @@ -128,7 +128,7 @@ Then edit `rtsp-simple-server.yml` and replace everything inside section `paths`
```yaml
paths:
cam:
runOnInit: gst-launch-1.0 rpicamsrc preview=false bitrate=2000000 keyframe-interval=50 ! video/x-h264,width=1920,height=1080,framerate=25/1 ! rtspclientsink location=rtsp://localhost:8554/$RTSP_PATH
runOnInit: gst-launch-1.0 rpicamsrc preview=false bitrate=2000000 keyframe-interval=50 ! video/x-h264,width=1920,height=1080,framerate=25/1 ! rtspclientsink location=rtsp://localhost:$RTSP_PORT/$RTSP_PATH
runOnInitRestart: yes
```
@ -140,7 +140,7 @@ Edit `rtsp-simple-server.yml` and replace everything inside section `paths` with @@ -140,7 +140,7 @@ Edit `rtsp-simple-server.yml` and replace everything inside section `paths` with
```yaml
paths:
ondemand:
runOnDemand: ffmpeg -re -stream_loop -1 -i file.ts -c copy -f rtsp rtsp://localhost:8554/$RTSP_PATH
runOnDemand: ffmpeg -re -stream_loop -1 -i file.ts -c copy -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH
runOnDemandRestart: yes
```
@ -153,7 +153,7 @@ To change the format, codec or compression of a stream, you can use _FFmpeg_ or @@ -153,7 +153,7 @@ To change the format, codec or compression of a stream, you can use _FFmpeg_ or
paths:
all:
original:
runOnPublish: ffmpeg -i rtsp://localhost:8554/$RTSP_PATH -b:a 64k -c:v libx264 -preset ultrafast -b:v 500k -max_muxing_queue_size 1024 -f rtsp rtsp://localhost:8554/compressed
runOnPublish: ffmpeg -i rtsp://localhost:$RTSP_PORT/$RTSP_PATH -b:a 64k -c:v libx264 -preset ultrafast -b:v 500k -max_muxing_queue_size 1024 -f rtsp rtsp://localhost:$RTSP_PORT/compressed
runOnPublishRestart: yes
```

44
client/client.go

@ -97,14 +97,15 @@ type Parent interface { @@ -97,14 +97,15 @@ type Parent interface {
}
type Client struct {
wg *sync.WaitGroup
stats *stats.Stats
serverUdpRtp *serverudp.Server
serverUdpRtcp *serverudp.Server
rtspPort int
readTimeout time.Duration
runOnConnect string
runOnConnectRestart bool
protocols map[gortsplib.StreamProtocol]struct{}
wg *sync.WaitGroup
stats *stats.Stats
serverUdpRtp *serverudp.Server
serverUdpRtcp *serverudp.Server
conn *gortsplib.ConnServer
parent Parent
@ -128,27 +129,29 @@ type Client struct { @@ -128,27 +129,29 @@ type Client struct {
}
func New(
wg *sync.WaitGroup,
stats *stats.Stats,
serverUdpRtp *serverudp.Server,
serverUdpRtcp *serverudp.Server,
rtspPort int,
readTimeout time.Duration,
writeTimeout time.Duration,
runOnConnect string,
runOnConnectRestart bool,
protocols map[gortsplib.StreamProtocol]struct{},
wg *sync.WaitGroup,
stats *stats.Stats,
serverUdpRtp *serverudp.Server,
serverUdpRtcp *serverudp.Server,
nconn net.Conn,
parent Parent) *Client {
c := &Client{
wg: wg,
stats: stats,
serverUdpRtp: serverUdpRtp,
serverUdpRtcp: serverUdpRtcp,
rtspPort: rtspPort,
readTimeout: readTimeout,
runOnConnect: runOnConnect,
runOnConnectRestart: runOnConnectRestart,
protocols: protocols,
wg: wg,
stats: stats,
serverUdpRtp: serverUdpRtp,
serverUdpRtcp: serverUdpRtcp,
conn: gortsplib.NewConnServer(gortsplib.ConnServerConf{
Conn: nconn,
ReadTimeout: readTimeout,
@ -201,7 +204,10 @@ func (c *Client) run() { @@ -201,7 +204,10 @@ func (c *Client) run() {
var onConnectCmd *externalcmd.ExternalCmd
if c.runOnConnect != "" {
onConnectCmd = externalcmd.New(c.runOnConnect, c.runOnConnectRestart, "")
onConnectCmd = externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{
Path: "",
Port: strconv.FormatInt(int64(c.rtspPort), 10),
})
}
for {
@ -936,8 +942,10 @@ func (c *Client) runPlay() bool { @@ -936,8 +942,10 @@ func (c *Client) runPlay() bool {
var onReadCmd *externalcmd.ExternalCmd
if c.path.Conf().RunOnRead != "" {
onReadCmd = externalcmd.New(c.path.Conf().RunOnRead,
c.path.Conf().RunOnReadRestart, c.path.Name())
onReadCmd = externalcmd.New(c.path.Conf().RunOnRead, c.path.Conf().RunOnReadRestart, externalcmd.Environment{
Path: c.path.Name(),
Port: strconv.FormatInt(int64(c.rtspPort), 10),
})
}
if c.streamProtocol == gortsplib.StreamProtocolUDP {
@ -1111,8 +1119,10 @@ func (c *Client) runRecord() bool { @@ -1111,8 +1119,10 @@ func (c *Client) runRecord() bool {
var onPublishCmd *externalcmd.ExternalCmd
if c.path.Conf().RunOnPublish != "" {
onPublishCmd = externalcmd.New(c.path.Conf().RunOnPublish,
c.path.Conf().RunOnPublishRestart, c.path.Name())
onPublishCmd = externalcmd.New(c.path.Conf().RunOnPublish, c.path.Conf().RunOnPublishRestart, externalcmd.Environment{
Path: c.path.Name(),
Port: strconv.FormatInt(int64(c.rtspPort), 10),
})
}
if c.streamProtocol == gortsplib.StreamProtocolUDP {

17
clientman/clientman.go

@ -20,6 +20,7 @@ type Parent interface { @@ -20,6 +20,7 @@ type Parent interface {
}
type ClientManager struct {
rtspPort int
readTimeout time.Duration
writeTimeout time.Duration
runOnConnect string
@ -44,6 +45,7 @@ type ClientManager struct { @@ -44,6 +45,7 @@ type ClientManager struct {
}
func New(
rtspPort int,
readTimeout time.Duration,
writeTimeout time.Duration,
runOnConnect string,
@ -57,6 +59,7 @@ func New( @@ -57,6 +59,7 @@ func New(
parent Parent) *ClientManager {
cm := &ClientManager{
rtspPort: rtspPort,
readTimeout: readTimeout,
writeTimeout: writeTimeout,
runOnConnect: runOnConnect,
@ -94,17 +97,9 @@ outer: @@ -94,17 +97,9 @@ outer:
for {
select {
case conn := <-cm.serverTcp.Accept():
c := client.New(&cm.wg,
cm.stats,
cm.serverUdpRtp,
cm.serverUdpRtcp,
cm.readTimeout,
cm.writeTimeout,
cm.runOnConnect,
cm.runOnConnectRestart,
cm.protocols,
conn,
cm)
c := client.New(cm.rtspPort, cm.readTimeout, cm.writeTimeout,
cm.runOnConnect, cm.runOnConnectRestart, cm.protocols, &cm.wg,
cm.stats, cm.serverUdpRtp, cm.serverUdpRtcp, conn, cm)
cm.clients[c] = struct{}{}
case c := <-cm.pathMan.ClientClose():

24
externalcmd/externalcmd.go

@ -12,10 +12,15 @@ const ( @@ -12,10 +12,15 @@ const (
retryPause = 5 * time.Second
)
type Environment struct {
Path string
Port string
}
type ExternalCmd struct {
cmdstr string
restart bool
pathName string
cmdstr string
restart bool
env Environment
// in
terminate chan struct{}
@ -24,11 +29,11 @@ type ExternalCmd struct { @@ -24,11 +29,11 @@ type ExternalCmd struct {
done chan struct{}
}
func New(cmdstr string, restart bool, pathName string) *ExternalCmd {
func New(cmdstr string, restart bool, env Environment) *ExternalCmd {
e := &ExternalCmd{
cmdstr: cmdstr,
restart: restart,
pathName: pathName,
env: env,
terminate: make(chan struct{}),
done: make(chan struct{}),
}
@ -79,16 +84,19 @@ func (e *ExternalCmd) runInner() bool { @@ -79,16 +84,19 @@ func (e *ExternalCmd) runInner() bool {
// on Windows the shell is not used and command is started directly
// variables are replaced manually in order to guarantee compatibility
// with Linux commands
args := strings.Fields(strings.ReplaceAll(e.cmdstr, "$RTSP_PATH", e.pathName))
tmp := strings.ReplaceAll(e.cmdstr, "$RTSP_PATH", e.env.Path)
tmp = strings.ReplaceAll(tmp, "$RTSP_PORT", e.env.Port)
args := strings.Fields(tmp)
cmd = exec.Command(args[0], args[1:]...)
} else {
cmd = exec.Command("/bin/sh", "-c", "exec "+e.cmdstr)
}
// variables are inserted into the environment
cmd.Env = append(os.Environ(),
"RTSP_PATH="+e.pathName,
"RTSP_PATH="+e.env.Path,
"RTSP_PORT="+e.env.Port,
)
cmd.Stdout = os.Stdout

13
main.go

@ -175,13 +175,14 @@ func (p *program) createResources(initial bool) error { @@ -175,13 +175,14 @@ func (p *program) createResources(initial bool) error {
}
if p.pathMan == nil {
p.pathMan = pathman.New(p.conf.ReadTimeout, p.conf.WriteTimeout,
p.conf.AuthMethodsParsed, p.conf.Paths, p.stats, p)
p.pathMan = pathman.New(p.conf.RtspPort, p.conf.ReadTimeout,
p.conf.WriteTimeout, p.conf.AuthMethodsParsed, p.conf.Paths,
p.stats, p)
}
if p.clientMan == nil {
p.clientMan = clientman.New(p.conf.ReadTimeout, p.conf.WriteTimeout,
p.conf.RunOnConnect, p.conf.RunOnConnectRestart,
p.clientMan = clientman.New(p.conf.RtspPort, p.conf.ReadTimeout,
p.conf.WriteTimeout, p.conf.RunOnConnect, p.conf.RunOnConnectRestart,
p.conf.ProtocolsParsed, p.stats, p.serverUdpRtp, p.serverUdpRtcp,
p.pathMan, p.serverTcp, p)
}
@ -280,7 +281,8 @@ func (p *program) reloadConf() error { @@ -280,7 +281,8 @@ func (p *program) reloadConf() error {
}
closePathMan := false
if conf.ReadTimeout != p.conf.ReadTimeout ||
if conf.RtspPort != p.conf.RtspPort ||
conf.ReadTimeout != p.conf.ReadTimeout ||
conf.WriteTimeout != p.conf.WriteTimeout ||
!reflect.DeepEqual(conf.AuthMethodsParsed, p.conf.AuthMethodsParsed) {
closePathMan = true
@ -293,6 +295,7 @@ func (p *program) reloadConf() error { @@ -293,6 +295,7 @@ func (p *program) reloadConf() error {
closeServerUdpRtcp ||
closeServerTcp ||
closePathMan ||
conf.RtspPort != p.conf.RtspPort ||
conf.ReadTimeout != p.conf.ReadTimeout ||
conf.WriteTimeout != p.conf.WriteTimeout ||
conf.RunOnConnect != p.conf.RunOnConnect ||

6
main_test.go

@ -692,7 +692,7 @@ func TestRedirect(t *testing.T) { @@ -692,7 +692,7 @@ func TestRedirect(t *testing.T) {
func TestRunOnDemand(t *testing.T) {
p1, err := testProgram("paths:\n" +
" all:\n" +
" runOnDemand: ffmpeg -hide_banner -loglevel error -re -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:8554/$RTSP_PATH\n")
" runOnDemand: ffmpeg -hide_banner -loglevel error -re -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH\n")
require.NoError(t, err)
defer p1.close()
@ -716,7 +716,7 @@ func TestHotReloading(t *testing.T) { @@ -716,7 +716,7 @@ func TestHotReloading(t *testing.T) {
err := ioutil.WriteFile(confPath, []byte("paths:\n"+
" test1:\n"+
" runOnDemand: ffmpeg -hide_banner -loglevel error -re -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:8554/$RTSP_PATH\n"),
" runOnDemand: ffmpeg -hide_banner -loglevel error -re -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH\n"),
0644)
require.NoError(t, err)
@ -742,7 +742,7 @@ func TestHotReloading(t *testing.T) { @@ -742,7 +742,7 @@ func TestHotReloading(t *testing.T) {
err = ioutil.WriteFile(confPath, []byte("paths:\n"+
" test2:\n"+
" runOnDemand: ffmpeg -hide_banner -loglevel error -re -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:8554/$RTSP_PATH\n"),
" runOnDemand: ffmpeg -hide_banner -loglevel error -re -i testimages/ffmpeg/emptyvideo.ts -c copy -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH\n"),
0644)
require.NoError(t, err)

16
path/path.go

@ -2,6 +2,7 @@ package path @@ -2,6 +2,7 @@ package path
import (
"fmt"
"strconv"
"strings"
"sync"
"sync/atomic"
@ -125,6 +126,7 @@ const ( @@ -125,6 +126,7 @@ const (
)
type Path struct {
rtspPort int
readTimeout time.Duration
writeTimeout time.Duration
confName string
@ -165,6 +167,7 @@ type Path struct { @@ -165,6 +167,7 @@ type Path struct {
}
func New(
rtspPort int,
readTimeout time.Duration,
writeTimeout time.Duration,
confName string,
@ -175,6 +178,7 @@ func New( @@ -175,6 +178,7 @@ func New(
parent Parent) *Path {
pa := &Path{
rtspPort: rtspPort,
readTimeout: readTimeout,
writeTimeout: writeTimeout,
confName: confName,
@ -225,8 +229,10 @@ func (pa *Path) run() { @@ -225,8 +229,10 @@ func (pa *Path) run() {
if pa.conf.RunOnInit != "" {
pa.Log("on init command started")
pa.onInitCmd = externalcmd.New(pa.conf.RunOnInit,
pa.conf.RunOnInitRestart, pa.name)
pa.onInitCmd = externalcmd.New(pa.conf.RunOnInit, pa.conf.RunOnInitRestart, externalcmd.Environment{
Path: pa.name,
Port: strconv.FormatInt(int64(pa.rtspPort), 10),
})
}
outer:
@ -575,8 +581,10 @@ func (pa *Path) onClientDescribe(c *client.Client) { @@ -575,8 +581,10 @@ func (pa *Path) onClientDescribe(c *client.Client) {
if pa.conf.RunOnDemand != "" {
if pa.onDemandCmd == nil {
pa.Log("on demand command started")
pa.onDemandCmd = externalcmd.New(pa.conf.RunOnDemand,
pa.conf.RunOnDemandRestart, pa.name)
pa.onDemandCmd = externalcmd.New(pa.conf.RunOnDemand, pa.conf.RunOnDemandRestart, externalcmd.Environment{
Path: pa.name,
Port: strconv.FormatInt(int64(pa.rtspPort), 10),
})
if pa.sourceState != sourceStateWaitingDescribe {
pa.describeTimer = time.NewTimer(pa.conf.RunOnDemandStartTimeout)

18
pathman/pathman.go

@ -20,6 +20,7 @@ type Parent interface { @@ -20,6 +20,7 @@ type Parent interface {
}
type PathManager struct {
rtspPort int
readTimeout time.Duration
writeTimeout time.Duration
authMethods []headers.AuthMethod
@ -44,6 +45,7 @@ type PathManager struct { @@ -44,6 +45,7 @@ type PathManager struct {
}
func New(
rtspPort int,
readTimeout time.Duration,
writeTimeout time.Duration,
authMethods []headers.AuthMethod,
@ -52,6 +54,7 @@ func New( @@ -52,6 +54,7 @@ func New(
parent Parent) *PathManager {
pm := &PathManager{
rtspPort: rtspPort,
readTimeout: readTimeout,
writeTimeout: writeTimeout,
authMethods: authMethods,
@ -155,9 +158,8 @@ outer: @@ -155,9 +158,8 @@ outer:
// create path if it doesn't exist
if _, ok := pm.paths[req.PathName]; !ok {
pa := path.New(
pm.readTimeout, pm.writeTimeout, pathName, pathConf, req.PathName,
&pm.wg, pm.stats, pm)
pa := path.New(pm.rtspPort, pm.readTimeout, pm.writeTimeout,
pathName, pathConf, req.PathName, &pm.wg, pm.stats, pm)
pm.paths[req.PathName] = pa
}
@ -179,9 +181,8 @@ outer: @@ -179,9 +181,8 @@ outer:
// create path if it doesn't exist
if _, ok := pm.paths[req.PathName]; !ok {
pa := path.New(
pm.readTimeout, pm.writeTimeout, pathName, pathConf, req.PathName,
&pm.wg, pm.stats, pm)
pa := path.New(pm.rtspPort, pm.readTimeout, pm.writeTimeout,
pathName, pathConf, req.PathName, &pm.wg, pm.stats, pm)
pm.paths[req.PathName] = pa
}
@ -254,9 +255,8 @@ outer: @@ -254,9 +255,8 @@ outer:
func (pm *PathManager) createPaths() {
for pathName, pathConf := range pm.pathConfs {
if pathConf.Regexp == nil {
pa := path.New(
pm.readTimeout, pm.writeTimeout, pathName, pathConf, pathName,
&pm.wg, pm.stats, pm)
pa := path.New(pm.rtspPort, pm.readTimeout, pm.writeTimeout,
pathName, pathConf, pathName, &pm.wg, pm.stats, pm)
pm.paths[pathName] = pa
}
}

5
rtsp-simple-server.yml

@ -29,6 +29,7 @@ logFile: rtsp-simple-server.log @@ -29,6 +29,7 @@ logFile: rtsp-simple-server.log
# command to run when a client connects to the server.
# this is terminated with SIGINT when a client disconnects from the server.
# the server port is available in the RTSP_PORT variable.
# the restart parameter allows to restart the command if it exits suddenly.
runOnConnect:
runOnConnectRestart: no
@ -83,6 +84,7 @@ paths: @@ -83,6 +84,7 @@ paths:
# this can be used to publish a stream and keep it always opened.
# this is terminated with SIGINT when the program closes.
# the path name is available in the RTSP_PATH variable.
# the server port is available in the RTSP_PORT variable.
# the restart parameter allows to restart the command if it exits suddenly.
runOnInit:
runOnInitRestart: no
@ -91,6 +93,7 @@ paths: @@ -91,6 +93,7 @@ paths:
# this can be used to publish a stream on demand.
# this is terminated with SIGINT when the path is not requested anymore.
# the path name is available in the RTSP_PATH variable.
# the server port is available in the RTSP_PORT variable.
# the restart parameter allows to restart the command if it exits suddenly.
runOnDemand:
runOnDemandRestart: no
@ -104,6 +107,7 @@ paths: @@ -104,6 +107,7 @@ paths:
# command to run when a client starts publishing.
# this is terminated with SIGINT when a client stops publishing.
# the path name is available in the RTSP_PATH variable.
# the server port is available in the RTSP_PORT variable.
# the restart parameter allows to restart the command if it exits suddenly.
runOnPublish:
runOnPublishRestart: no
@ -111,6 +115,7 @@ paths: @@ -111,6 +115,7 @@ paths:
# command to run when a clients starts reading.
# this is terminated with SIGINT when a client stops reading.
# the path name is available in the RTSP_PATH variable.
# the server port is available in the RTSP_PORT variable.
# the restart parameter allows to restart the command if it exits suddenly.
runOnRead:
runOnReadRestart: no

Loading…
Cancel
Save