mirror of https://bitbucket.org/ausocean/av.git
exp/rvcl: adding default config option and opening VLC in the case of RTP output
If no config is given as arguments or file, then a default config is used. This is file input (25 FPS) with MPEG-TS packetization and RTP output. If RTP output is selected, a VLC window to receive the stream is opened.
This commit is contained in:
parent
93d5eb1638
commit
a4a409b4f5
123
exp/rvcl/main.go
123
exp/rvcl/main.go
|
@ -60,12 +60,10 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
|
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/container/mts"
|
"bitbucket.org/ausocean/av/container/mts"
|
||||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||||
"bitbucket.org/ausocean/av/revid"
|
"bitbucket.org/ausocean/av/revid"
|
||||||
|
@ -82,12 +80,8 @@ const (
|
||||||
|
|
||||||
// Logging configuration.
|
// Logging configuration.
|
||||||
const (
|
const (
|
||||||
logMaxSize = 500 // MB
|
logLevel = logger.Info
|
||||||
logMaxBackups = 10
|
logSuppress = true
|
||||||
logMaxAge = 28 // days
|
|
||||||
logLevel = logger.Debug
|
|
||||||
logPath = "/var/log/netsender/netsender.log"
|
|
||||||
logSuppress = false
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Misc consts.
|
// Misc consts.
|
||||||
|
@ -96,15 +90,56 @@ const (
|
||||||
profilePath = "rvcl.prof"
|
profilePath = "rvcl.prof"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Netsender conf consts.
|
||||||
|
const (
|
||||||
|
cfgPath = "/etc/netsender.conf"
|
||||||
|
fMode = 0777
|
||||||
|
)
|
||||||
|
|
||||||
// canProfile is set to false with revid-cli is built with "-tags profile".
|
// canProfile is set to false with revid-cli is built with "-tags profile".
|
||||||
var canProfile = false
|
var canProfile = false
|
||||||
|
|
||||||
// The logger that will be used throughout.
|
// The logger that will be used throughout.
|
||||||
var log *logger.Logger
|
var log *logger.Logger
|
||||||
|
|
||||||
|
// stdoutLogger provides an io.Writer for the purpose of capturing stdout from
|
||||||
|
// the VLC process and using the logger to capture and print to stdout of
|
||||||
|
// this process.
|
||||||
|
type stdoutLogger struct {
|
||||||
|
l *logger.Logger
|
||||||
|
t string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *stdoutLogger) Write(d []byte) (int, error) {
|
||||||
|
sl.l.Info(sl.t + ": " + string(d))
|
||||||
|
return len(d), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// stderrLogger provides an io.Writer for the purpose of capturing stderr from
|
||||||
|
// the VLC process and using the logger to capture and print to stdout of
|
||||||
|
// this process.
|
||||||
|
type stderrLogger struct {
|
||||||
|
l *logger.Logger
|
||||||
|
t string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *stderrLogger) Write(d []byte) (int, error) {
|
||||||
|
sl.l.Error(sl.t + ": " + string(d))
|
||||||
|
return len(d), nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mts.Meta = meta.NewWith([][2]string{{metaPreambleKey, metaPreambleData}})
|
mts.Meta = meta.NewWith([][2]string{{metaPreambleKey, metaPreambleData}})
|
||||||
|
|
||||||
|
// Create logger that methods will be called on by the netsender client and
|
||||||
|
// revid to log messages. Logs will go the lumberjack logger to handle file
|
||||||
|
// writing of messages.
|
||||||
|
log = logger.New(
|
||||||
|
logLevel,
|
||||||
|
os.Stdout,
|
||||||
|
logSuppress,
|
||||||
|
)
|
||||||
|
|
||||||
// If built with profile tag, we will start CPU profiling.
|
// If built with profile tag, we will start CPU profiling.
|
||||||
if canProfile {
|
if canProfile {
|
||||||
profile()
|
profile()
|
||||||
|
@ -115,6 +150,7 @@ func main() {
|
||||||
var (
|
var (
|
||||||
configPtr = flag.String("config", "", "Provide configuration JSON to revid (see readme for further information).")
|
configPtr = flag.String("config", "", "Provide configuration JSON to revid (see readme for further information).")
|
||||||
configFilePtr = flag.String("config-file", "", "Location of revid configuration file (see readme for further information).")
|
configFilePtr = flag.String("config-file", "", "Location of revid configuration file (see readme for further information).")
|
||||||
|
rtpAddrPtr = flag.String("addr", "localhost:6970", "RTP destination address (<ip>:<port>)(common port=6970)")
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
@ -124,62 +160,79 @@ func main() {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
case *configPtr != "" && *configFilePtr != "": // This doesn't make sense so panic.
|
// This doesn't make sense so panic.
|
||||||
|
case *configPtr != "" && *configFilePtr != "":
|
||||||
panic("cannot define both command-line config and file config")
|
panic("cannot define both command-line config and file config")
|
||||||
case *configPtr != "": // Decode JSON file to map.
|
|
||||||
|
// Decode JSON file to map.
|
||||||
|
case *configPtr != "":
|
||||||
err = json.Unmarshal([]byte(*configPtr), &cfg)
|
err = json.Unmarshal([]byte(*configPtr), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("could not decode JSON config: %v", err))
|
log.Fatal("could not decode JSON config", "error", err)
|
||||||
}
|
}
|
||||||
case *configFilePtr != "": // Decode JSON string to map from command line flag.
|
|
||||||
|
// Decode JSON string to map from command line flag.
|
||||||
|
case *configFilePtr != "":
|
||||||
f, err := os.Open(*configFilePtr)
|
f, err := os.Open(*configFilePtr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("could not open config file: %v", err))
|
log.Fatal("could not open config file", "error", err)
|
||||||
}
|
}
|
||||||
err = json.NewDecoder(f).Decode(&cfg)
|
err = json.NewDecoder(f).Decode(&cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("could not decode JSON config: %v", err))
|
log.Fatal("could not decode JSON config", "error", err)
|
||||||
}
|
}
|
||||||
default: // No config information has been provided; give empty map to force defaults.
|
|
||||||
cfg = map[string]string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create logger that methods will be called on by the netsender client and
|
// No config information has been provided; provide a default config map.
|
||||||
// revid to log messages. Logs will go the lumberjack logger to handle file
|
default:
|
||||||
// writing of messages.
|
cfg = map[string]string{
|
||||||
log = logger.New(
|
"Input": "File",
|
||||||
logLevel,
|
"InputPath": "../../../test/test-data/av/input/betterInput.h264",
|
||||||
&lumberjack.Logger{
|
"FileFPS": "25",
|
||||||
Filename: logPath,
|
"Output": "RTP",
|
||||||
MaxSize: logMaxSize, // MB
|
"RTPAddress": *rtpAddrPtr,
|
||||||
MaxBackups: logMaxBackups,
|
"Loop": "true",
|
||||||
MaxAge: logMaxAge, // days
|
}
|
||||||
},
|
}
|
||||||
logSuppress,
|
log.Info("got config", "config", cfg)
|
||||||
)
|
|
||||||
|
|
||||||
// Create a netsender client. This is used only for HTTP sending of media
|
// Create a netsender client. This is used only for HTTP sending of media
|
||||||
// in this binary.
|
// in this binary.
|
||||||
ns, err := netsender.New(log, nil, nil, nil, nil)
|
ns, err := netsender.New(log, nil, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, pkg+"could not initialise netsender client: "+err.Error())
|
log.Fatal("could not initialise netsender client", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the revid client, responsible for media collection and processing.
|
||||||
|
log.Info("got creating revid client")
|
||||||
rv, err := revid.New(config.Config{Logger: log}, ns)
|
rv, err := revid.New(config.Config{Logger: log}, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("could not create revid: %v", err))
|
log.Fatal("could not create revid", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure revid with configuration map obtained through flags or file.
|
// Configure revid with configuration map obtained through flags or file.
|
||||||
// If config is empty, defaults will be adopted by revid.
|
// If config is empty, defaults will be adopted by revid.
|
||||||
|
log.Info("updating revid with config")
|
||||||
err = rv.Update(cfg)
|
err = rv.Update(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("could not update revid config: %v", err))
|
log.Fatal("could not update revid config", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("starting revid")
|
||||||
err = rv.Start()
|
err = rv.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("could not start revid: %v", err))
|
log.Fatal("could not start revid", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If output is RTP, open up a VLC window to see stream.
|
||||||
|
if v, ok := cfg["Output"]; ok && v == "RTP" {
|
||||||
|
log.Info("opening vlc window")
|
||||||
|
cmd := exec.Command("vlc", "rtp://"+*rtpAddrPtr)
|
||||||
|
cmd.Stdout = &stdoutLogger{log, "VLC STDOUT"}
|
||||||
|
cmd.Stderr = &stderrLogger{log, "VLC STDERR"}
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("could not run vlc command", "error", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run indefinitely.
|
// Run indefinitely.
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
bitbucket.org/ausocean/iot v1.3.0
|
bitbucket.org/ausocean/iot v1.3.0
|
||||||
bitbucket.org/ausocean/utils v1.2.14
|
bitbucket.org/ausocean/utils v1.2.15
|
||||||
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7
|
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7
|
||||||
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480
|
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480
|
||||||
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884
|
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -4,6 +4,8 @@ bitbucket.org/ausocean/utils v1.2.11 h1:zA0FOaPjN960ryp8PKCkV5y50uWBYrIxCVnXjwbv
|
||||||
bitbucket.org/ausocean/utils v1.2.11/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
bitbucket.org/ausocean/utils v1.2.11/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
||||||
bitbucket.org/ausocean/utils v1.2.14 h1:v5eBYavkEqKOBCppR6P451eT9UT/CQReMsOZZBUPX3Q=
|
bitbucket.org/ausocean/utils v1.2.14 h1:v5eBYavkEqKOBCppR6P451eT9UT/CQReMsOZZBUPX3Q=
|
||||||
bitbucket.org/ausocean/utils v1.2.14/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
bitbucket.org/ausocean/utils v1.2.14/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
||||||
|
bitbucket.org/ausocean/utils v1.2.15 h1:Pz99ZfobdhACTtU6oj9BTyBcNSQulLvPT7wq4P343Es=
|
||||||
|
bitbucket.org/ausocean/utils v1.2.15/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7 h1:LdOc9B9Bj6LEsKiXShkLA3/kpxXb6LJpH+ekU2krbzw=
|
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7 h1:LdOc9B9Bj6LEsKiXShkLA3/kpxXb6LJpH+ekU2krbzw=
|
||||||
|
|
Loading…
Reference in New Issue