mirror of https://bitbucket.org/ausocean/av.git
Merged in updating-logging (pull request #479)
using latest version of utils and using latest logging package Resolves issue #372 Approved-by: Trek Hopton
This commit is contained in:
commit
d64e46794a
|
@ -52,7 +52,7 @@ import (
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/iot/pi/sds"
|
"bitbucket.org/ausocean/iot/pi/sds"
|
||||||
"bitbucket.org/ausocean/iot/pi/smartlogger"
|
"bitbucket.org/ausocean/iot/pi/smartlogger"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"bitbucket.org/ausocean/utils/pool"
|
"bitbucket.org/ausocean/utils/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -94,37 +94,37 @@ type parameters struct {
|
||||||
bits int // sample bit size, 16 by default
|
bits int // sample bit size, 16 by default
|
||||||
}
|
}
|
||||||
|
|
||||||
var log *logger.Logger
|
var log logging.Logger
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var logLevel int
|
var logLevel int
|
||||||
flag.IntVar(&logLevel, "LogLevel", int(logger.Debug), "Specifies log level")
|
flag.IntVar(&logLevel, "LogLevel", int(logging.Debug), "Specifies log level")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
validLogLevel := true
|
validLogLevel := true
|
||||||
if logLevel < int(logger.Debug) || logLevel > int(logger.Fatal) {
|
if logLevel < int(logging.Debug) || logLevel > int(logging.Fatal) {
|
||||||
logLevel = int(logger.Info)
|
logLevel = int(logging.Info)
|
||||||
validLogLevel = false
|
validLogLevel = false
|
||||||
}
|
}
|
||||||
|
|
||||||
logSender := smartlogger.New(logPath)
|
logSender := smartlogger.New(logPath)
|
||||||
log = logger.New(int8(logLevel), &logSender.LogRoller, true)
|
log = logging.New(int8(logLevel), &logSender.LogRoller, true)
|
||||||
log.Log(logger.Info, "log-netsender: Logger Initialized")
|
log.Info("log-netsender: Logger Initialized")
|
||||||
if !validLogLevel {
|
if !validLogLevel {
|
||||||
log.Log(logger.Error, "invalid log level was defaulted to Info")
|
log.Error("invalid log level was defaulted to Info")
|
||||||
}
|
}
|
||||||
|
|
||||||
var ac audioClient
|
var ac audioClient
|
||||||
var err error
|
var err error
|
||||||
ac.ns, err = netsender.New(log, nil, sds.ReadSystem, nil)
|
ac.ns, err = netsender.New(log, nil, sds.ReadSystem, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, "netsender.Init failed", "error", err.Error())
|
log.Fatal("netsender.Init failed", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get audio params and store the current var sum.
|
// Get audio params and store the current var sum.
|
||||||
vars, err := ac.ns.Vars()
|
vars, err := ac.ns.Vars()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Warning, "netsender.Vars failed; using defaults", "error", err.Error())
|
log.Warning("netsender.Vars failed; using defaults", "error", err.Error())
|
||||||
}
|
}
|
||||||
ac.params(vars)
|
ac.params(vars)
|
||||||
ac.vs = ac.ns.VarSum()
|
ac.vs = ac.ns.VarSum()
|
||||||
|
@ -132,14 +132,14 @@ func main() {
|
||||||
// Open the requested audio device.
|
// Open the requested audio device.
|
||||||
err = ac.open()
|
err = ac.open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, "yalsa.open failed", "error", err.Error())
|
log.Fatal("yalsa.open failed", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture audio in periods of ac.period seconds, and buffer rbDuration seconds in total.
|
// Capture audio in periods of ac.period seconds, and buffer rbDuration seconds in total.
|
||||||
ab := ac.dev.NewBufferDuration(time.Second * time.Duration(ac.period))
|
ab := ac.dev.NewBufferDuration(time.Second * time.Duration(ac.period))
|
||||||
sf, err := pcm.SFFromString(ab.Format.SampleFormat.String())
|
sf, err := pcm.SFFromString(ab.Format.SampleFormat.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Error, err.Error())
|
log.Error(err.Error())
|
||||||
}
|
}
|
||||||
cf := pcm.BufferFormat{
|
cf := pcm.BufferFormat{
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
|
@ -220,9 +220,9 @@ func (ac *audioClient) params(vars map[string]string) bool {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
ac.parameters = p
|
ac.parameters = p
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
log.Log(logger.Debug, "params changed")
|
log.Debug("params changed")
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "parameters", "mode", p.mode, "source", p.source, "rate", p.rate, "period", p.period, "channels", p.channels, "bits", p.bits)
|
log.Debug("parameters", "mode", p.mode, "source", p.source, "rate", p.rate, "period", p.period, "channels", p.channels, "bits", p.bits)
|
||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,11 +230,11 @@ func (ac *audioClient) params(vars map[string]string) bool {
|
||||||
// If name is empty, the first recording device is used.
|
// If name is empty, the first recording device is used.
|
||||||
func (ac *audioClient) open() error {
|
func (ac *audioClient) open() error {
|
||||||
if ac.dev != nil {
|
if ac.dev != nil {
|
||||||
log.Log(logger.Debug, "closing", "source", ac.source)
|
log.Debug("closing", "source", ac.source)
|
||||||
ac.dev.Close()
|
ac.dev.Close()
|
||||||
ac.dev = nil
|
ac.dev = nil
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "opening", "source", ac.source)
|
log.Debug("opening", "source", ac.source)
|
||||||
|
|
||||||
cards, err := yalsa.OpenCards()
|
cards, err := yalsa.OpenCards()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -261,14 +261,14 @@ func (ac *audioClient) open() error {
|
||||||
if ac.dev == nil {
|
if ac.dev == nil {
|
||||||
return errors.New("No audio source found")
|
return errors.New("No audio source found")
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "found audio source", "source", ac.dev.Title)
|
log.Debug("found audio source", "source", ac.dev.Title)
|
||||||
|
|
||||||
// ToDo: time out if Open takes too long.
|
// ToDo: time out if Open takes too long.
|
||||||
err = ac.dev.Open()
|
err = ac.dev.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "opened audio source")
|
log.Debug("opened audio source")
|
||||||
|
|
||||||
_, err = ac.dev.NegotiateChannels(defaultChannels)
|
_, err = ac.dev.NegotiateChannels(defaultChannels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -290,7 +290,7 @@ func (ac *audioClient) open() error {
|
||||||
_, err = ac.dev.NegotiateRate(r)
|
_, err = ac.dev.NegotiateRate(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
foundRate = true
|
foundRate = true
|
||||||
log.Log(logger.Debug, "sample rate set", "rate", r)
|
log.Debug("sample rate set", "rate", r)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,12 +298,12 @@ func (ac *audioClient) open() error {
|
||||||
|
|
||||||
// If no easily divisible rate is found, then use the default rate.
|
// If no easily divisible rate is found, then use the default rate.
|
||||||
if !foundRate {
|
if !foundRate {
|
||||||
log.Log(logger.Warning, "no available device sample-rates are divisible by the requested rate. Default rate will be used. Resampling may fail.", "rateRequested", ac.rate)
|
log.Warning("no available device sample-rates are divisible by the requested rate. Default rate will be used. Resampling may fail.", "rateRequested", ac.rate)
|
||||||
_, err = ac.dev.NegotiateRate(defaultFrameRate)
|
_, err = ac.dev.NegotiateRate(defaultFrameRate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "sample rate set", "rate", defaultFrameRate)
|
log.Debug("sample rate set", "rate", defaultFrameRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fmt yalsa.FormatType
|
var fmt yalsa.FormatType
|
||||||
|
@ -329,7 +329,7 @@ func (ac *audioClient) open() error {
|
||||||
if err = ac.dev.Prepare(); err != nil {
|
if err = ac.dev.Prepare(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "successfully negotiated ALSA params")
|
log.Debug("successfully negotiated ALSA params")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,16 +347,16 @@ func (ac *audioClient) input() {
|
||||||
time.Sleep(time.Duration(ac.period) * time.Second)
|
time.Sleep(time.Duration(ac.period) * time.Second)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "recording audio for period", "seconds", ac.period)
|
log.Debug("recording audio for period", "seconds", ac.period)
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
err := ac.dev.Read(ac.pb.Data)
|
err := ac.dev.Read(ac.pb.Data)
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Debug, "device.Read failed", "error", err.Error())
|
log.Debug("device.Read failed", "error", err.Error())
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
err = ac.open() // re-open
|
err = ac.open() // re-open
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, "yalsa.open failed", "error", err.Error())
|
log.Fatal("yalsa.open failed", "error", err.Error())
|
||||||
}
|
}
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
continue
|
continue
|
||||||
|
@ -364,17 +364,17 @@ func (ac *audioClient) input() {
|
||||||
|
|
||||||
toWrite := ac.formatBuffer()
|
toWrite := ac.formatBuffer()
|
||||||
|
|
||||||
log.Log(logger.Debug, "audio format conversion has been performed where needed")
|
log.Debug("audio format conversion has been performed where needed")
|
||||||
|
|
||||||
var n int
|
var n int
|
||||||
n, err = ac.buf.Write(toWrite.Data)
|
n, err = ac.buf.Write(toWrite.Data)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
log.Log(logger.Debug, "wrote audio to ringbuffer", "length", n)
|
log.Debug("wrote audio to ringbuffer", "length", n)
|
||||||
case pool.ErrDropped:
|
case pool.ErrDropped:
|
||||||
log.Log(logger.Warning, "dropped audio")
|
log.Warning("dropped audio")
|
||||||
default:
|
default:
|
||||||
log.Log(logger.Error, "unexpected ringbuffer error", "error", err.Error())
|
log.Error("unexpected ringbuffer error", "error", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,7 @@ func (ac *audioClient) output() {
|
||||||
ip := ac.ns.Param("ip")
|
ip := ac.ns.Param("ip")
|
||||||
mp, err := strconv.Atoi(ac.ns.Param("mp"))
|
mp, err := strconv.Atoi(ac.ns.Param("mp"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, "mp not an integer")
|
log.Fatal("mp not an integer")
|
||||||
}
|
}
|
||||||
|
|
||||||
report := true // Report non-audio data.
|
report := true // Report non-audio data.
|
||||||
|
@ -425,7 +425,7 @@ func (ac *audioClient) output() {
|
||||||
goto sleep
|
goto sleep
|
||||||
}
|
}
|
||||||
if n != len(buf) {
|
if n != len(buf) {
|
||||||
log.Log(logger.Error, "unexpected length from read", "length", n)
|
log.Error("unexpected length from read", "length", n)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if report {
|
if report {
|
||||||
|
@ -452,14 +452,14 @@ func (ac *audioClient) output() {
|
||||||
if pin.Name[0] == 'X' {
|
if pin.Name[0] == 'X' {
|
||||||
err := sds.ReadSystem(&pins[i])
|
err := sds.ReadSystem(&pins[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Warning, "sds.ReadSystem failed", "error", err.Error())
|
log.Warning("sds.ReadSystem failed", "error", err.Error())
|
||||||
// Pin.Value defaults to -1 upon error, so OK to continue.
|
// Pin.Value defaults to -1 upon error, so OK to continue.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, rc, err = ac.ns.Send(netsender.RequestPoll, pins)
|
_, rc, err = ac.ns.Send(netsender.RequestPoll, pins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Debug, "netsender.Send failed", "error", err.Error())
|
log.Debug("netsender.Send failed", "error", err.Error())
|
||||||
goto sleep
|
goto sleep
|
||||||
}
|
}
|
||||||
if report {
|
if report {
|
||||||
|
@ -469,20 +469,20 @@ func (ac *audioClient) output() {
|
||||||
if rc == netsender.ResponseUpdate {
|
if rc == netsender.ResponseUpdate {
|
||||||
_, err = ac.ns.Config()
|
_, err = ac.ns.Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Warning, "netsender.Config failed", "error", err.Error())
|
log.Warning("netsender.Config failed", "error", err.Error())
|
||||||
goto sleep
|
goto sleep
|
||||||
}
|
}
|
||||||
ip = ac.ns.Param("ip")
|
ip = ac.ns.Param("ip")
|
||||||
mp, err = strconv.Atoi(ac.ns.Param("mp"))
|
mp, err = strconv.Atoi(ac.ns.Param("mp"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, "mp not an integer")
|
log.Fatal("mp not an integer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ac.vs != ac.ns.VarSum() {
|
if ac.vs != ac.ns.VarSum() {
|
||||||
vars, err := ac.ns.Vars()
|
vars, err := ac.ns.Vars()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Error, "netsender.Vars failed", "error", err.Error())
|
log.Error("netsender.Vars failed", "error", err.Error())
|
||||||
goto sleep
|
goto sleep
|
||||||
}
|
}
|
||||||
ac.params(vars) // ToDo: re-open device if audio params have changed.
|
ac.params(vars) // ToDo: re-open device if audio params have changed.
|
||||||
|
@ -511,20 +511,20 @@ func read(rb *pool.Buffer, buf []byte) (int, error) {
|
||||||
case pool.ErrTimeout:
|
case pool.ErrTimeout:
|
||||||
return 0, nil
|
return 0, nil
|
||||||
case io.EOF:
|
case io.EOF:
|
||||||
log.Log(logger.Error, "unexpected EOF from pool.Next")
|
log.Error("unexpected EOF from pool.Next")
|
||||||
return 0, io.ErrUnexpectedEOF
|
return 0, io.ErrUnexpectedEOF
|
||||||
default:
|
default:
|
||||||
log.Log(logger.Error, "unexpected error from pool.Next", "error", err.Error())
|
log.Error("unexpected error from pool.Next", "error", err.Error())
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := io.ReadFull(rb, buf[:chunk.Len()])
|
n, err := io.ReadFull(rb, buf[:chunk.Len()])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Error, "unexpected error from pool.Read", "error", err.Error())
|
log.Error("unexpected error from pool.Read", "error", err.Error())
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Log(logger.Debug, "read audio from ringbuffer", "length", n)
|
log.Debug("read audio from ringbuffer", "length", n)
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +549,7 @@ func (ac *audioClient) formatBuffer() pcm.Buffer {
|
||||||
// Convert channels.
|
// Convert channels.
|
||||||
if ac.pb.Format.Channels == 2 && wantChannels == 1 {
|
if ac.pb.Format.Channels == 2 && wantChannels == 1 {
|
||||||
if formatted, err = pcm.StereoToMono(ac.pb); err != nil {
|
if formatted, err = pcm.StereoToMono(ac.pb); err != nil {
|
||||||
log.Log(logger.Warning, "channel conversion failed, audio has remained stereo", "error", err.Error())
|
log.Warning("channel conversion failed, audio has remained stereo", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
formatted.Format.Channels = 1
|
formatted.Format.Channels = 1
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ func (ac *audioClient) formatBuffer() pcm.Buffer {
|
||||||
formatted, err = pcm.Resample(ac.pb, uint(wantRate))
|
formatted, err = pcm.Resample(ac.pb, uint(wantRate))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Warning, "rate conversion failed, audio has remained original rate", "error", err.Error())
|
log.Warning("rate conversion failed, audio has remained original rate", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
formatted.Format.Rate = uint(wantRate)
|
formatted.Format.Rate = uint(wantRate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ import (
|
||||||
"bitbucket.org/ausocean/iot/pi/netlogger"
|
"bitbucket.org/ausocean/iot/pi/netlogger"
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/iot/pi/sds"
|
"bitbucket.org/ausocean/iot/pi/sds"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ const (
|
||||||
logMaxSize = 500 // MB
|
logMaxSize = 500 // MB
|
||||||
logMaxBackup = 10
|
logMaxBackup = 10
|
||||||
logMaxAge = 28 // days
|
logMaxAge = 28 // days
|
||||||
logVerbosity = logger.Debug
|
logVerbosity = logging.Debug
|
||||||
logSuppress = true
|
logSuppress = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ func main() {
|
||||||
nl := netlogger.New()
|
nl := netlogger.New()
|
||||||
|
|
||||||
// Create logger that we call methods on to l.
|
// Create logger that we call methods on to l.
|
||||||
l := logger.New(logVerbosity, io.MultiWriter(fileLog, nl), logSuppress)
|
l := logging.New(logVerbosity, io.MultiWriter(fileLog, nl), logSuppress)
|
||||||
|
|
||||||
// Call initialisation code that is specific to the platform (pi 0 or 3).
|
// Call initialisation code that is specific to the platform (pi 0 or 3).
|
||||||
initCommand(l)
|
initCommand(l)
|
||||||
|
@ -89,7 +89,7 @@ func main() {
|
||||||
// Create netsender client.
|
// Create netsender client.
|
||||||
ns, err := netsender.New(l, nil, readPin(), nil)
|
ns, err := netsender.New(l, nil, readPin(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Fatal, "could not initialise netsender client", "error", err)
|
l.Fatal( "could not initialise netsender client", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This routine will deal with things that need to happen with the netsender client.
|
// This routine will deal with things that need to happen with the netsender client.
|
||||||
|
@ -104,28 +104,28 @@ func main() {
|
||||||
// stdout and stderr.
|
// stdout and stderr.
|
||||||
outPipe, err := cmd.StdoutPipe()
|
outPipe, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "failed to pipe stdout", "error", err)
|
l.Error( "failed to pipe stdout", "error", err)
|
||||||
}
|
}
|
||||||
errPipe, err := cmd.StderrPipe()
|
errPipe, err := cmd.StderrPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "failed to pipe stderr", "error", err)
|
l.Error( "failed to pipe stderr", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start playback of the audio file.
|
// Start playback of the audio file.
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "start failed", "error", err.Error())
|
l.Error( "start failed", "error", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
numPlays++
|
numPlays++
|
||||||
l.Log(logger.Debug, "playing audio", "numPlays", numPlays)
|
l.Debug( "playing audio", "numPlays", numPlays)
|
||||||
|
|
||||||
// Copy any std out to a buffer for logging.
|
// Copy any std out to a buffer for logging.
|
||||||
var outBuff bytes.Buffer
|
var outBuff bytes.Buffer
|
||||||
go func() {
|
go func() {
|
||||||
_, err = io.Copy(&outBuff, outPipe)
|
_, err = io.Copy(&outBuff, outPipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "failed to copy out pipe", "error", err)
|
l.Error( "failed to copy out pipe", "error", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -134,38 +134,38 @@ func main() {
|
||||||
go func() {
|
go func() {
|
||||||
_, err = io.Copy(&errBuff, errPipe)
|
_, err = io.Copy(&errBuff, errPipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "failed to copy error pipe", "error", err)
|
l.Error( "failed to copy error pipe", "error", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for playback to complete.
|
// Wait for playback to complete.
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "failed to wait for execution finish", "error", err.Error())
|
l.Error( "failed to wait for execution finish", "error", err.Error())
|
||||||
}
|
}
|
||||||
l.Log(logger.Debug, "stdout received", "stdout", string(outBuff.Bytes()))
|
l.Debug( "stdout received", "stdout", string(outBuff.Bytes()))
|
||||||
|
|
||||||
// If there was any errors on stderr, l them.
|
// If there was any errors on stderr, l them.
|
||||||
if errBuff.Len() != 0 {
|
if errBuff.Len() != 0 {
|
||||||
l.Log(logger.Error, "errors from stderr", "stderr", string(errBuff.Bytes()))
|
l.Error( "errors from stderr", "stderr", string(errBuff.Bytes()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run is a routine to deal with netsender related tasks.
|
// run is a routine to deal with netsender related tasks.
|
||||||
func run(ns *netsender.Sender, l *logger.Logger, nl *netlogger.Logger) {
|
func run(ns *netsender.Sender, l logging.Logger, nl *netlogger.Logger) {
|
||||||
var vs int
|
var vs int
|
||||||
for {
|
for {
|
||||||
err := ns.Run()
|
err := ns.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, "Run Failed. Retrying...", "error", err)
|
l.Warning( "Run Failed. Retrying...", "error", err)
|
||||||
time.Sleep(netSendRetryTime)
|
time.Sleep(netSendRetryTime)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = nl.Send(ns)
|
err = nl.Send(ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, "Logs could not be sent", "error", err.Error())
|
l.Warning( "Logs could not be sent", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// If var sum hasn't changed we skip rest of loop.
|
// If var sum hasn't changed we skip rest of loop.
|
||||||
|
@ -178,7 +178,7 @@ func run(ns *netsender.Sender, l *logger.Logger, nl *netlogger.Logger) {
|
||||||
|
|
||||||
vars, err := ns.Vars()
|
vars, err := ns.Vars()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "netSender failed to get vars", "error", err)
|
l.Error( "netSender failed to get vars", "error", err)
|
||||||
time.Sleep(netSendRetryTime)
|
time.Sleep(netSendRetryTime)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ func run(ns *netsender.Sender, l *logger.Logger, nl *netlogger.Logger) {
|
||||||
// Configure looper based on vars.
|
// Configure looper based on vars.
|
||||||
err = update(vars)
|
err = update(vars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, "couldn't update with new vars", "error", err)
|
l.Warning( "couldn't update with new vars", "error", err)
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -202,20 +202,20 @@ func run(ns *netsender.Sender, l *logger.Logger, nl *netlogger.Logger) {
|
||||||
|
|
||||||
// checkPath wraps the use of lookPath to check the existence of executables
|
// checkPath wraps the use of lookPath to check the existence of executables
|
||||||
// that will be used by the audio looper.
|
// that will be used by the audio looper.
|
||||||
func checkPath(cmd string, l *logger.Logger) {
|
func checkPath(cmd string, l logging.Logger) {
|
||||||
path, err := exec.LookPath(cmd)
|
path, err := exec.LookPath(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Fatal, fmt.Sprintf("couldn't find %s", cmd), "error", err)
|
l.Fatal( fmt.Sprintf("couldn't find %s", cmd), "error", err)
|
||||||
}
|
}
|
||||||
l.Log(logger.Debug, fmt.Sprintf("found %s", cmd), "path", path)
|
l.Debug( fmt.Sprintf("found %s", cmd), "path", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep uses a delay to halt the program based on the monitoring period
|
// sleep uses a delay to halt the program based on the monitoring period
|
||||||
// netsender parameter (mp) defined in the netsender.conf config.
|
// netsender parameter (mp) defined in the netsender.conf config.
|
||||||
func sleep(ns *netsender.Sender, l *logger.Logger) {
|
func sleep(ns *netsender.Sender, l logging.Logger) {
|
||||||
t, err := strconv.Atoi(ns.Param("mp"))
|
t, err := strconv.Atoi(ns.Param("mp"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "could not get sleep time, using default", "error", err)
|
l.Error( "could not get sleep time, using default", "error", err)
|
||||||
t = defaultSleepTime
|
t = defaultSleepTime
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(t) * time.Second)
|
time.Sleep(time.Duration(t) * time.Second)
|
||||||
|
|
|
@ -28,11 +28,11 @@ LICENSE
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const audioCmd = "play"
|
const audioCmd = "play"
|
||||||
|
|
||||||
func initCommand(l *logger.Logger) {
|
func initCommand(l logging.Logger) {
|
||||||
panic("looper is intended to be run on a Raspberry Pi 0 or 3.")
|
panic("looper is intended to be run on a Raspberry Pi 0 or 3.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,12 +33,12 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const audioCmd = "play"
|
const audioCmd = "play"
|
||||||
|
|
||||||
func initCommand(l *logger.Logger) {
|
func initCommand(l logging.Logger) {
|
||||||
const (
|
const (
|
||||||
cardPath = "/usr/share/doc/audioInjector/asound.state.RCA.thru.test"
|
cardPath = "/usr/share/doc/audioInjector/asound.state.RCA.thru.test"
|
||||||
retryDur = 5 * time.Second
|
retryDur = 5 * time.Second
|
||||||
|
@ -52,7 +52,7 @@ func initCommand(l *logger.Logger) {
|
||||||
cmdInit := exec.Command(alsactl, "-f", cardPath, "restore")
|
cmdInit := exec.Command(alsactl, "-f", cardPath, "restore")
|
||||||
err := cmdInit.Run()
|
err := cmdInit.Run()
|
||||||
for err != nil {
|
for err != nil {
|
||||||
l.Log(logger.Warning, "alsactl run failed, retrying...", "error", err)
|
l.Warning( "alsactl run failed, retrying...", "error", err)
|
||||||
time.Sleep(retryDur)
|
time.Sleep(retryDur)
|
||||||
err = cmdInit.Run()
|
err = cmdInit.Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ LICENSE
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const audioCmd = "omxplayer"
|
const audioCmd = "omxplayer"
|
||||||
|
|
||||||
func initCommand(l *logger.Logger) { checkPath(audioCmd, l) }
|
func initCommand(l logging.Logger) { checkPath(audioCmd, l) }
|
||||||
|
|
|
@ -69,7 +69,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/iot/pi/netlogger"
|
"bitbucket.org/ausocean/iot/pi/netlogger"
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Copyright information prefixed to all metadata.
|
// Copyright information prefixed to all metadata.
|
||||||
|
@ -84,7 +84,7 @@ const (
|
||||||
logMaxSize = 500 // MB
|
logMaxSize = 500 // MB
|
||||||
logMaxBackup = 10
|
logMaxBackup = 10
|
||||||
logMaxAge = 28 // days
|
logMaxAge = 28 // days
|
||||||
logVerbosity = logger.Info
|
logVerbosity = logging.Info
|
||||||
logSuppress = true
|
logSuppress = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -132,13 +132,13 @@ func main() {
|
||||||
|
|
||||||
// Create logger that we call methods on to log, which in turn writes to the
|
// Create logger that we call methods on to log, which in turn writes to the
|
||||||
// lumberjack and netloggers.
|
// lumberjack and netloggers.
|
||||||
log := logger.New(logVerbosity, io.MultiWriter(fileLog, netLog), logSuppress)
|
log := logging.New(logVerbosity, io.MultiWriter(fileLog, netLog), logSuppress)
|
||||||
|
|
||||||
// If rv has been built with the profile tag, then we'll start a CPU profile.
|
// If rv has been built with the profile tag, then we'll start a CPU profile.
|
||||||
if canProfile {
|
if canProfile {
|
||||||
profile(log)
|
profile(log)
|
||||||
defer pprof.StopCPUProfile()
|
defer pprof.StopCPUProfile()
|
||||||
log.Log(logger.Info, "profiling started")
|
log.Info( "profiling started")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -146,26 +146,26 @@ func main() {
|
||||||
p *turbidityProbe
|
p *turbidityProbe
|
||||||
)
|
)
|
||||||
|
|
||||||
p, err := NewTurbidityProbe(*log, 60*time.Second)
|
p, err := NewTurbidityProbe(log, 60*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, "could not create new turbidity probe", "error", err.Error())
|
log.Fatal( "could not create new turbidity probe", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Log(logger.Debug, "initialising netsender client")
|
log.Debug( "initialising netsender client")
|
||||||
ns, err := netsender.New(log, nil, readPin(p, rv, log), nil, netsender.WithVarTypes(createVarMap()))
|
ns, err := netsender.New(log, nil, readPin(p, rv, log), nil, netsender.WithVarTypes(createVarMap()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, pkg+"could not initialise netsender client: "+err.Error())
|
log.Fatal( pkg+"could not initialise netsender client: "+err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Log(logger.Debug, "initialising revid")
|
log.Debug( "initialising revid")
|
||||||
rv, err = revid.New(config.Config{Logger: log}, ns)
|
rv, err = revid.New(config.Config{Logger: log}, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, pkg+"could not initialise revid", "error", err.Error())
|
log.Fatal( pkg+"could not initialise revid", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = rv.SetProbe(p)
|
err = rv.SetProbe(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Error, pkg+"could not set probe", "error", err.Error())
|
log.Error( pkg+"could not set probe", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: Problems were encountered with communicating with RTSP inputs. When trying to
|
// NB: Problems were encountered with communicating with RTSP inputs. When trying to
|
||||||
|
@ -174,89 +174,89 @@ func main() {
|
||||||
// a better way to solve this problem.
|
// a better way to solve this problem.
|
||||||
time.Sleep(runPreDelay)
|
time.Sleep(runPreDelay)
|
||||||
|
|
||||||
log.Log(logger.Debug, "beginning main loop")
|
log.Debug( "beginning main loop")
|
||||||
run(rv, ns, log, netLog, p)
|
run(rv, ns, log, netLog, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run starts the main loop. This will run netsender on every pass of the loop
|
// run starts the main loop. This will run netsender on every pass of the loop
|
||||||
// (sleeping inbetween), check vars, and if changed, update revid as appropriate.
|
// (sleeping inbetween), check vars, and if changed, update revid as appropriate.
|
||||||
func run(rv *revid.Revid, ns *netsender.Sender, l *logger.Logger, nl *netlogger.Logger, p *turbidityProbe) {
|
func run(rv *revid.Revid, ns *netsender.Sender, l logging.Logger, nl *netlogger.Logger, p *turbidityProbe) {
|
||||||
var vs int
|
var vs int
|
||||||
for {
|
for {
|
||||||
l.Log(logger.Debug, "running netsender")
|
l.Debug( "running netsender")
|
||||||
err := ns.Run()
|
err := ns.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, pkg+"Run Failed. Retrying...", "error", err.Error())
|
l.Warning( pkg+"Run Failed. Retrying...", "error", err.Error())
|
||||||
time.Sleep(netSendRetryTime)
|
time.Sleep(netSendRetryTime)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Log(logger.Debug, "sending logs")
|
l.Debug( "sending logs")
|
||||||
err = nl.Send(ns)
|
err = nl.Send(ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, pkg+"Logs could not be sent", "error", err.Error())
|
l.Warning( pkg+"Logs could not be sent", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Log(logger.Debug, "checking varsum")
|
l.Debug( "checking varsum")
|
||||||
newVs := ns.VarSum()
|
newVs := ns.VarSum()
|
||||||
if vs == newVs {
|
if vs == newVs {
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
vs = newVs
|
vs = newVs
|
||||||
l.Log(logger.Info, "varsum changed", "vs", vs)
|
l.Info( "varsum changed", "vs", vs)
|
||||||
|
|
||||||
l.Log(logger.Debug, "getting new vars")
|
l.Debug( "getting new vars")
|
||||||
vars, err := ns.Vars()
|
vars, err := ns.Vars()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, pkg+"netSender failed to get vars", "error", err.Error())
|
l.Error( pkg+"netSender failed to get vars", "error", err.Error())
|
||||||
time.Sleep(netSendRetryTime)
|
time.Sleep(netSendRetryTime)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
l.Log(logger.Debug, "got new vars", "vars", vars)
|
l.Debug( "got new vars", "vars", vars)
|
||||||
|
|
||||||
// Configure revid based on the vars.
|
// Configure revid based on the vars.
|
||||||
l.Log(logger.Debug, "updating revid's configuration")
|
l.Debug( "updating revid's configuration")
|
||||||
err = rv.Update(vars)
|
err = rv.Update(vars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, pkg+"couldn't update revid", "error", err.Error())
|
l.Warning( pkg+"couldn't update revid", "error", err.Error())
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
l.Log(logger.Info, "revid successfully reconfigured")
|
l.Info( "revid successfully reconfigured")
|
||||||
|
|
||||||
// Update transform matrix based on new revid variables.
|
// Update transform matrix based on new revid variables.
|
||||||
err = p.Update(rv.Config().TransformMatrix)
|
err = p.Update(rv.Config().TransformMatrix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, "could not update turbidity probe", "error", err.Error())
|
l.Error( "could not update turbidity probe", "error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Log(logger.Debug, "checking mode")
|
l.Debug( "checking mode")
|
||||||
switch ns.Mode() {
|
switch ns.Mode() {
|
||||||
case modePaused:
|
case modePaused:
|
||||||
l.Log(logger.Debug, "mode is Paused, stopping revid")
|
l.Debug( "mode is Paused, stopping revid")
|
||||||
rv.Stop()
|
rv.Stop()
|
||||||
case modeNormal, modeLoop:
|
case modeNormal, modeLoop:
|
||||||
l.Log(logger.Debug, "mode is Normal or Loop, starting revid")
|
l.Debug( "mode is Normal or Loop, starting revid")
|
||||||
err = rv.Start()
|
err = rv.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, pkg+"could not start revid", "error", err.Error())
|
l.Error( pkg+"could not start revid", "error", err.Error())
|
||||||
ns.SetMode(modePaused, &vs)
|
ns.SetMode(modePaused, &vs)
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case modeBurst:
|
case modeBurst:
|
||||||
l.Log(logger.Debug, "mode is Burst, bursting revid")
|
l.Debug( "mode is Burst, bursting revid")
|
||||||
err = rv.Burst()
|
err = rv.Burst()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Warning, pkg+"could not start burst", "error", err.Error())
|
l.Warning( pkg+"could not start burst", "error", err.Error())
|
||||||
ns.SetMode(modePaused, &vs)
|
ns.SetMode(modePaused, &vs)
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ns.SetMode(modePaused, &vs)
|
ns.SetMode(modePaused, &vs)
|
||||||
}
|
}
|
||||||
l.Log(logger.Info, "revid updated with new mode")
|
l.Info( "revid updated with new mode")
|
||||||
|
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
}
|
}
|
||||||
|
@ -272,32 +272,32 @@ func createVarMap() map[string]string {
|
||||||
|
|
||||||
// profile opens a file to hold CPU profiling metrics and then starts the
|
// profile opens a file to hold CPU profiling metrics and then starts the
|
||||||
// CPU profiler.
|
// CPU profiler.
|
||||||
func profile(l *logger.Logger) {
|
func profile(l logging.Logger) {
|
||||||
f, err := os.Create(profilePath)
|
f, err := os.Create(profilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Fatal, pkg+"could not create CPU profile", "error", err.Error())
|
l.Fatal( pkg+"could not create CPU profile", "error", err.Error())
|
||||||
}
|
}
|
||||||
if err := pprof.StartCPUProfile(f); err != nil {
|
if err := pprof.StartCPUProfile(f); err != nil {
|
||||||
l.Log(logger.Fatal, pkg+"could not start CPU profile", "error", err.Error())
|
l.Fatal( pkg+"could not start CPU profile", "error", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep uses a delay to halt the program based on the monitoring period
|
// sleep uses a delay to halt the program based on the monitoring period
|
||||||
// netsender parameter (mp) defined in the netsender.conf config.
|
// netsender parameter (mp) defined in the netsender.conf config.
|
||||||
func sleep(ns *netsender.Sender, l *logger.Logger) {
|
func sleep(ns *netsender.Sender, l logging.Logger) {
|
||||||
l.Log(logger.Debug, "sleeping")
|
l.Debug( "sleeping")
|
||||||
t, err := strconv.Atoi(ns.Param("mp"))
|
t, err := strconv.Atoi(ns.Param("mp"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Log(logger.Error, pkg+"could not get sleep time, using default", "error", err)
|
l.Error( pkg+"could not get sleep time, using default", "error", err)
|
||||||
t = defaultSleepTime
|
t = defaultSleepTime
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(t) * time.Second)
|
time.Sleep(time.Duration(t) * time.Second)
|
||||||
l.Log(logger.Debug, "finished sleeping")
|
l.Debug( "finished sleeping")
|
||||||
}
|
}
|
||||||
|
|
||||||
// readPin provides a callback function of consistent signature for use by
|
// readPin provides a callback function of consistent signature for use by
|
||||||
// netsender to retrieve software defined pin values e.g. revid bitrate.
|
// netsender to retrieve software defined pin values e.g. revid bitrate.
|
||||||
func readPin(p *turbidityProbe, rv *revid.Revid, l *logger.Logger) func(pin *netsender.Pin) error {
|
func readPin(p *turbidityProbe, rv *revid.Revid, l logging.Logger) func(pin *netsender.Pin) error {
|
||||||
return func(pin *netsender.Pin) error {
|
return func(pin *netsender.Pin) error {
|
||||||
switch {
|
switch {
|
||||||
case pin.Name == bitratePin:
|
case pin.Name == bitratePin:
|
||||||
|
|
|
@ -41,7 +41,7 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/h264"
|
"bitbucket.org/ausocean/av/codec/h264"
|
||||||
"bitbucket.org/ausocean/av/turbidity"
|
"bitbucket.org/ausocean/av/turbidity"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Misc constants.
|
// Misc constants.
|
||||||
|
@ -67,14 +67,14 @@ type turbidityProbe struct {
|
||||||
delay time.Duration
|
delay time.Duration
|
||||||
ticker time.Ticker
|
ticker time.Ticker
|
||||||
ts *turbidity.TurbiditySensor
|
ts *turbidity.TurbiditySensor
|
||||||
log logger.Logger
|
log logging.Logger
|
||||||
buffer *bytes.Buffer
|
buffer *bytes.Buffer
|
||||||
transform []float64
|
transform []float64
|
||||||
trimCounter int
|
trimCounter int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTurbidityProbe returns a new turbidity probe.
|
// NewTurbidityProbe returns a new turbidity probe.
|
||||||
func NewTurbidityProbe(log logger.Logger, delay time.Duration) (*turbidityProbe, error) {
|
func NewTurbidityProbe(log logging.Logger, delay time.Duration) (*turbidityProbe, error) {
|
||||||
tp := new(turbidityProbe)
|
tp := new(turbidityProbe)
|
||||||
tp.log = log
|
tp.log = log
|
||||||
tp.delay = delay
|
tp.delay = delay
|
||||||
|
@ -107,7 +107,7 @@ func (tp *turbidityProbe) Write(p []byte) (int, error) {
|
||||||
}
|
}
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
} else {
|
} else {
|
||||||
tp.log.Log(logger.Debug, "trim successful", "keyframe error counter", tp.trimCounter)
|
tp.log.Debug( "trim successful", "keyframe error counter", tp.trimCounter)
|
||||||
tp.trimCounter = 0
|
tp.trimCounter = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ func (tp *turbidityProbe) Write(p []byte) (int, error) {
|
||||||
tp.buffer.Reset()
|
tp.buffer.Reset()
|
||||||
return 0, fmt.Errorf("could not write trimmed video to buffer: %w", err)
|
return 0, fmt.Errorf("could not write trimmed video to buffer: %w", err)
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "video trimmed, write keyframe complete", "size(bytes)", n)
|
tp.log.Debug( "video trimmed, write keyframe complete", "size(bytes)", n)
|
||||||
} else if tp.buffer.Len() < bufferLimit {
|
} else if tp.buffer.Len() < bufferLimit {
|
||||||
// Buffer size is limited to speed up decoding.
|
// Buffer size is limited to speed up decoding.
|
||||||
_, err := tp.buffer.Write(p)
|
_, err := tp.buffer.Write(p)
|
||||||
|
@ -128,13 +128,13 @@ func (tp *turbidityProbe) Write(p []byte) (int, error) {
|
||||||
// Buffer is large enough to begin turbidity calculation.
|
// Buffer is large enough to begin turbidity calculation.
|
||||||
select {
|
select {
|
||||||
case <-tp.ticker.C:
|
case <-tp.ticker.C:
|
||||||
tp.log.Log(logger.Debug, "beginning turbidity calculation")
|
tp.log.Debug( "beginning turbidity calculation")
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
err := tp.turbidityCalculation()
|
err := tp.turbidityCalculation()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("could not calculate turbidity: %w", err)
|
return 0, fmt.Errorf("could not calculate turbidity: %w", err)
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "finished turbidity calculation", "total duration (sec)", time.Since(startTime).Seconds())
|
tp.log.Debug( "finished turbidity calculation", "total duration (sec)", time.Since(startTime).Seconds())
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,13 +155,13 @@ func (tp *turbidityProbe) Update(transformMatrix []float64) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Update the turbidity sensor with new transformation.
|
// Update the turbidity sensor with new transformation.
|
||||||
tp.log.Log(logger.Debug, "updating the transformation matrix")
|
tp.log.Debug( "updating the transformation matrix")
|
||||||
tp.transform = transformMatrix
|
tp.transform = transformMatrix
|
||||||
newTransform := floatToMat(tp.transform)
|
newTransform := floatToMat(tp.transform)
|
||||||
tp.ts.TransformMatrix = newTransform
|
tp.ts.TransformMatrix = newTransform
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "no change to the transformation matrix")
|
tp.log.Debug( "no change to the transformation matrix")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,13 +174,13 @@ func (tp *turbidityProbe) turbidityCalculation() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create temp file: %w", err)
|
return fmt.Errorf("failed to create temp file: %w", err)
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "writing to file", "buffer size(bytes)", tp.buffer.Len())
|
tp.log.Debug( "writing to file", "buffer size(bytes)", tp.buffer.Len())
|
||||||
|
|
||||||
_, err = file.Write(tp.buffer.Bytes())
|
_, err = file.Write(tp.buffer.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write to temporary file: %w", err)
|
return fmt.Errorf("failed to write to temporary file: %w", err)
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "write to file success", "buffer size(bytes)", tp.buffer.Len())
|
tp.log.Debug( "write to file success", "buffer size(bytes)", tp.buffer.Len())
|
||||||
tp.buffer.Reset()
|
tp.buffer.Reset()
|
||||||
|
|
||||||
// Open the video file.
|
// Open the video file.
|
||||||
|
@ -189,7 +189,7 @@ func (tp *turbidityProbe) turbidityCalculation() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open video file: %w", err)
|
return fmt.Errorf("failed to open video file: %w", err)
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "video capture open", "total duration (sec)", time.Since(startTime).Seconds())
|
tp.log.Debug( "video capture open", "total duration (sec)", time.Since(startTime).Seconds())
|
||||||
|
|
||||||
// Store each frame until maximum amount is reached.
|
// Store each frame until maximum amount is reached.
|
||||||
startTime = time.Now()
|
startTime = time.Now()
|
||||||
|
@ -199,7 +199,7 @@ func (tp *turbidityProbe) turbidityCalculation() error {
|
||||||
if len(imgs) <= 0 {
|
if len(imgs) <= 0 {
|
||||||
return errors.New("no frames found")
|
return errors.New("no frames found")
|
||||||
}
|
}
|
||||||
tp.log.Log(logger.Debug, "read time", "total duration (sec)", time.Since(startTime).Seconds())
|
tp.log.Debug( "read time", "total duration (sec)", time.Since(startTime).Seconds())
|
||||||
|
|
||||||
// Process video data to get saturation and contrast scores.
|
// Process video data to get saturation and contrast scores.
|
||||||
res, err := tp.ts.Evaluate(imgs)
|
res, err := tp.ts.Evaluate(imgs)
|
||||||
|
|
|
@ -32,7 +32,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type turbidityProbe struct {
|
type turbidityProbe struct {
|
||||||
|
@ -40,7 +40,7 @@ type turbidityProbe struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTurbidityProbe returns an empty turbidity probe for CircleCI testing only.
|
// NewTurbidityProbe returns an empty turbidity probe for CircleCI testing only.
|
||||||
func NewTurbidityProbe(log logger.Logger, delay time.Duration) (*turbidityProbe, error) {
|
func NewTurbidityProbe(log logging.Logger, delay time.Duration) (*turbidityProbe, error) {
|
||||||
tp := new(turbidityProbe)
|
tp := new(turbidityProbe)
|
||||||
return tp, nil
|
return tp, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ func TestProbe(t *testing.T) {
|
||||||
MaxBackups: logMaxBackup,
|
MaxBackups: logMaxBackup,
|
||||||
MaxAge: logMaxAge,
|
MaxAge: logMaxAge,
|
||||||
}
|
}
|
||||||
log := logger.New(logVerbosity, io.MultiWriter(fileLog), logSuppress)
|
log := logging.New(logVerbosity, io.MultiWriter(fileLog), logSuppress)
|
||||||
updatedMatrix := []float64{-0.2731048063, -0.0020501869, 661.0275911942, 0.0014327789, -0.2699443748, 339.3921028016, 0.0000838317, 0.0000476486, 1.0}
|
updatedMatrix := []float64{-0.2731048063, -0.0020501869, 661.0275911942, 0.0014327789, -0.2699443748, 339.3921028016, 0.0000838317, 0.0000476486, 1.0}
|
||||||
|
|
||||||
ts, err := NewTurbidityProbe(*log, time.Microsecond)
|
ts, err := NewTurbidityProbe(log, time.Microsecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create turbidity probe")
|
t.Fatalf("failed to create turbidity probe")
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ LICENSE
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "bitbucket.org/ausocean/utils/logger"
|
import "bitbucket.org/ausocean/utils/logging"
|
||||||
|
|
||||||
const audioCmd = ""
|
const audioCmd = ""
|
||||||
|
|
||||||
func initCommand(log *logger.Logger) {}
|
func initCommand(log logging.Logger) {}
|
||||||
|
|
|
@ -45,7 +45,7 @@ import (
|
||||||
"bitbucket.org/ausocean/iot/pi/gpio"
|
"bitbucket.org/ausocean/iot/pi/gpio"
|
||||||
"bitbucket.org/ausocean/iot/pi/netlogger"
|
"bitbucket.org/ausocean/iot/pi/netlogger"
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"github.com/kidoman/embd"
|
"github.com/kidoman/embd"
|
||||||
_ "github.com/kidoman/embd/host/rpi"
|
_ "github.com/kidoman/embd/host/rpi"
|
||||||
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
@ -63,7 +63,7 @@ const (
|
||||||
logMaxSize = 500 // MB
|
logMaxSize = 500 // MB
|
||||||
logMaxBackup = 10
|
logMaxBackup = 10
|
||||||
logMaxAge = 28 // days
|
logMaxAge = 28 // days
|
||||||
logVerbosity = logger.Info
|
logVerbosity = logging.Info
|
||||||
logSuppress = true
|
logSuppress = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ func main() {
|
||||||
|
|
||||||
// Create logger that we call methods on to log, which in turn writes to the
|
// Create logger that we call methods on to log, which in turn writes to the
|
||||||
// lumberjack and netloggers.
|
// lumberjack and netloggers.
|
||||||
log := logger.New(logVerbosity, io.MultiWriter(fileLog, netLog), logSuppress)
|
log := logging.New(logVerbosity, io.MultiWriter(fileLog, netLog), logSuppress)
|
||||||
|
|
||||||
if *filePtr == "" {
|
if *filePtr == "" {
|
||||||
log.Fatal("no file path provided, check usage")
|
log.Fatal("no file path provided, check usage")
|
||||||
|
@ -138,7 +138,7 @@ func main() {
|
||||||
|
|
||||||
// run starts a control loop that runs netsender, sends logs, checks for var changes, and
|
// run starts a control loop that runs netsender, sends logs, checks for var changes, and
|
||||||
// if var changes, changes current mode (paused,audio playback or soundcheck)
|
// if var changes, changes current mode (paused,audio playback or soundcheck)
|
||||||
func run(rv *revid.Revid, ns *netsender.Sender, file *string, l *logger.Logger, nl *netlogger.Logger) {
|
func run(rv *revid.Revid, ns *netsender.Sender, file *string, l logging.Logger, nl *netlogger.Logger) {
|
||||||
var (
|
var (
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
audioQuit chan struct{}
|
audioQuit chan struct{}
|
||||||
|
@ -250,7 +250,7 @@ func run(rv *revid.Revid, ns *netsender.Sender, file *string, l *logger.Logger,
|
||||||
// playAudio is intended to be run as a routine. It will repeatedly play an audio file until
|
// playAudio is intended to be run as a routine. It will repeatedly play an audio file until
|
||||||
// a signal is received to return. The entire audio file is played before the termination
|
// a signal is received to return. The entire audio file is played before the termination
|
||||||
// signal chan is checked.
|
// signal chan is checked.
|
||||||
func playAudio(file *string, quit chan struct{}, wg *sync.WaitGroup, l *logger.Logger) {
|
func playAudio(file *string, quit chan struct{}, wg *sync.WaitGroup, l logging.Logger) {
|
||||||
var numPlays int
|
var numPlays int
|
||||||
for {
|
for {
|
||||||
cmd := exec.Command(audioCmd, *file)
|
cmd := exec.Command(audioCmd, *file)
|
||||||
|
@ -329,7 +329,7 @@ func stopAudio(wg *sync.WaitGroup, treating *bool, signal chan struct{}) {
|
||||||
|
|
||||||
// sleep uses a delay to halt the program based on the monitoring period
|
// sleep uses a delay to halt the program based on the monitoring period
|
||||||
// netsender parameter (mp) defined in the netsender.conf config.
|
// netsender parameter (mp) defined in the netsender.conf config.
|
||||||
func sleep(ns *netsender.Sender, l *logger.Logger) {
|
func sleep(ns *netsender.Sender, l logging.Logger) {
|
||||||
l.Debug("sleeping")
|
l.Debug("sleeping")
|
||||||
t, err := strconv.Atoi(ns.Param("mp"))
|
t, err := strconv.Atoi(ns.Param("mp"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -342,7 +342,7 @@ func sleep(ns *netsender.Sender, l *logger.Logger) {
|
||||||
|
|
||||||
// checkPath wraps the use of lookPath to check the existence of executables
|
// checkPath wraps the use of lookPath to check the existence of executables
|
||||||
// that will be used by the audio looper.
|
// that will be used by the audio looper.
|
||||||
func checkPath(cmd string, l *logger.Logger) {
|
func checkPath(cmd string, l logging.Logger) {
|
||||||
path, err := exec.LookPath(cmd)
|
path, err := exec.LookPath(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatal(fmt.Sprintf("couldn't find %s", cmd), "error", err)
|
l.Fatal(fmt.Sprintf("couldn't find %s", cmd), "error", err)
|
||||||
|
|
|
@ -30,9 +30,9 @@ LICENSE
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const audioCmd = "aplay"
|
const audioCmd = "aplay"
|
||||||
|
|
||||||
func initCommand(l *logger.Logger) { checkPath(audioCmd, l) }
|
func initCommand(l logging.Logger) { checkPath(audioCmd, l) }
|
||||||
|
|
|
@ -36,10 +36,10 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Log logger.LoggerIF
|
var Log logging.Logger
|
||||||
|
|
||||||
var noDelay = make(chan time.Time)
|
var noDelay = make(chan time.Time)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
var jpegTests = []struct {
|
var jpegTests = []struct {
|
||||||
|
@ -106,7 +106,7 @@ var jpegTests = []struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLex(t *testing.T) {
|
func TestLex(t *testing.T) {
|
||||||
Log = (*logger.TestLogger)(t)
|
Log = (*logging.TestLogger)(t)
|
||||||
for _, test := range jpegTests {
|
for _, test := range jpegTests {
|
||||||
var buf chunkEncoder
|
var buf chunkEncoder
|
||||||
err := Lex(&buf, bytes.NewReader(test.input), test.delay)
|
err := Lex(&buf, bytes.NewReader(test.input), test.delay)
|
||||||
|
|
|
@ -36,7 +36,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||||
"bitbucket.org/ausocean/av/container/mts/pes"
|
"bitbucket.org/ausocean/av/container/mts/pes"
|
||||||
"bitbucket.org/ausocean/av/container/mts/psi"
|
"bitbucket.org/ausocean/av/container/mts/psi"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"bitbucket.org/ausocean/utils/realtime"
|
"bitbucket.org/ausocean/utils/realtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -143,12 +143,12 @@ type Encoder struct {
|
||||||
patBytes, pmtBytes []byte
|
patBytes, pmtBytes []byte
|
||||||
|
|
||||||
// log is a function that will be used through the encoder code for logging.
|
// log is a function that will be used through the encoder code for logging.
|
||||||
log logger.LoggerIF
|
log logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder returns an Encoder with the specified media type and rate eg. if a video stream
|
// NewEncoder returns an Encoder with the specified media type and rate eg. if a video stream
|
||||||
// calls write for every frame, the rate will be the frame rate of the video.
|
// calls write for every frame, the rate will be the frame rate of the video.
|
||||||
func NewEncoder(dst io.WriteCloser, log logger.LoggerIF, options ...func(*Encoder) error) (*Encoder, error) {
|
func NewEncoder(dst io.WriteCloser, log logging.Logger, options ...func(*Encoder) error) (*Encoder, error) {
|
||||||
e := &Encoder{
|
e := &Encoder{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
writePeriod: time.Duration(float64(time.Second) / defaultRate),
|
writePeriod: time.Duration(float64(time.Second) / defaultRate),
|
||||||
|
@ -334,7 +334,7 @@ func (e *Encoder) ccFor(pid uint16) byte {
|
||||||
|
|
||||||
// updateMeta adds/updates a metaData descriptor in the given psi bytes using data
|
// updateMeta adds/updates a metaData descriptor in the given psi bytes using data
|
||||||
// contained in the global Meta struct.
|
// contained in the global Meta struct.
|
||||||
func updateMeta(b []byte, log logger.LoggerIF) ([]byte, error) {
|
func updateMeta(b []byte, log logging.Logger) ([]byte, error) {
|
||||||
p := psi.PSIBytes(b)
|
p := psi.PSIBytes(b)
|
||||||
if RealTime.IsSet() {
|
if RealTime.IsSet() {
|
||||||
t := strconv.Itoa(int(RealTime.Get().Unix()))
|
t := strconv.Itoa(int(RealTime.Get().Unix()))
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||||
"bitbucket.org/ausocean/av/container/mts/psi"
|
"bitbucket.org/ausocean/av/container/mts/psi"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type nopCloser struct{ io.Writer }
|
type nopCloser struct{ io.Writer }
|
||||||
|
@ -103,7 +103,7 @@ func TestEncodeVideo(t *testing.T) {
|
||||||
|
|
||||||
// Create the dst and write the test data to encoder.
|
// Create the dst and write the test data to encoder.
|
||||||
dst := &destination{}
|
dst := &destination{}
|
||||||
e, err := NewEncoder(nopCloser{dst}, (*logger.TestLogger)(t), PacketBasedPSI(psiSendCount), Rate(25), MediaType(EncodeH264))
|
e, err := NewEncoder(nopCloser{dst}, (*logging.TestLogger)(t), PacketBasedPSI(psiSendCount), Rate(25), MediaType(EncodeH264))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ func TestEncodePcm(t *testing.T) {
|
||||||
sampleSize := 2
|
sampleSize := 2
|
||||||
blockSize := 16000
|
blockSize := 16000
|
||||||
writeFreq := float64(sampleRate*sampleSize) / float64(blockSize)
|
writeFreq := float64(sampleRate*sampleSize) / float64(blockSize)
|
||||||
e, err := NewEncoder(nopCloser{&buf}, (*logger.TestLogger)(t), PacketBasedPSI(10), Rate(writeFreq), MediaType(EncodePCM))
|
e, err := NewEncoder(nopCloser{&buf}, (*logging.TestLogger)(t), PacketBasedPSI(10), Rate(writeFreq), MediaType(EncodePCM))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ const fps = 25
|
||||||
func TestMetaEncode1(t *testing.T) {
|
func TestMetaEncode1(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e, err := NewEncoder(nopCloser{&buf}, (*logger.TestLogger)(t))
|
e, err := NewEncoder(nopCloser{&buf}, (*logging.TestLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create encoder, failed with error: %v", err)
|
t.Fatalf("could not create encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ func TestMetaEncode1(t *testing.T) {
|
||||||
func TestMetaEncode2(t *testing.T) {
|
func TestMetaEncode2(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e, err := NewEncoder(nopCloser{&buf}, (*logger.TestLogger)(t))
|
e, err := NewEncoder(nopCloser{&buf}, (*logging.TestLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ func TestMetaEncode2(t *testing.T) {
|
||||||
func TestExtractMeta(t *testing.T) {
|
func TestExtractMeta(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e, err := NewEncoder(nopCloser{&buf}, (*logger.TestLogger)(t))
|
e, err := NewEncoder(nopCloser{&buf}, (*logging.TestLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||||
"bitbucket.org/ausocean/av/container/mts/pes"
|
"bitbucket.org/ausocean/av/container/mts/pes"
|
||||||
"bitbucket.org/ausocean/av/container/mts/psi"
|
"bitbucket.org/ausocean/av/container/mts/psi"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestGetPTSRange checks that GetPTSRange can correctly get the first and last
|
// TestGetPTSRange checks that GetPTSRange can correctly get the first and last
|
||||||
|
@ -678,7 +678,7 @@ func TestFindPSI(t *testing.T) {
|
||||||
}).Bytes()
|
}).Bytes()
|
||||||
|
|
||||||
Meta.Add(metaKey, test.meta)
|
Meta.Add(metaKey, test.meta)
|
||||||
pmtTable, err = updateMeta(pmtTable, (*logger.TestLogger)(t))
|
pmtTable, err = updateMeta(pmtTable, (*logging.TestLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not update meta for test %d", i)
|
t.Fatalf("could not update meta for test %d", i)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||||
"bitbucket.org/ausocean/av/container/mts/pes"
|
"bitbucket.org/ausocean/av/container/mts/pes"
|
||||||
"bitbucket.org/ausocean/av/container/mts/psi"
|
"bitbucket.org/ausocean/av/container/mts/psi"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestExtract checks that we can coorectly extract media, pts, id and meta from
|
// TestExtract checks that we can coorectly extract media, pts, id and meta from
|
||||||
|
@ -155,7 +155,7 @@ func writePSIWithMeta(b *bytes.Buffer, t *testing.T) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the meta in the pmt table.
|
// Update the meta in the pmt table.
|
||||||
pmtBytes, err = updateMeta(pmtBytes, (*logger.TestLogger)(t))
|
pmtBytes, err = updateMeta(pmtBytes, (*logging.TestLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/codec/pcm"
|
"bitbucket.org/ausocean/av/codec/pcm"
|
||||||
"bitbucket.org/ausocean/av/device"
|
"bitbucket.org/ausocean/av/device"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"bitbucket.org/ausocean/utils/pool"
|
"bitbucket.org/ausocean/utils/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ var (
|
||||||
|
|
||||||
// An ALSA device holds everything we need to know about the audio input stream and implements io.Reader and device.AVDevice.
|
// An ALSA device holds everything we need to know about the audio input stream and implements io.Reader and device.AVDevice.
|
||||||
type ALSA struct {
|
type ALSA struct {
|
||||||
l Logger // Logger for device's routines to log to.
|
l logging.Logger // Logger for device's routines to log to.
|
||||||
mode uint8 // Operating mode, either running, paused, or stopped.
|
mode uint8 // Operating mode, either running, paused, or stopped.
|
||||||
mu sync.Mutex // Provides synchronisation when changing modes concurrently.
|
mu sync.Mutex // Provides synchronisation when changing modes concurrently.
|
||||||
title string // Name of audio title, or empty for the default title.
|
title string // Name of audio title, or empty for the default title.
|
||||||
|
@ -99,15 +99,8 @@ type Config struct {
|
||||||
Codec string
|
Codec string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logger enables any implementation of a logger to be used.
|
|
||||||
// TODO: Make this part of the logger package.
|
|
||||||
type Logger interface {
|
|
||||||
SetLevel(int8)
|
|
||||||
Log(level int8, message string, params ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// New initializes and returns an ALSA device which has its logger set as the given logger.
|
// New initializes and returns an ALSA device which has its logger set as the given logger.
|
||||||
func New(l Logger) *ALSA { return &ALSA{l: l} }
|
func New(l logging.Logger) *ALSA { return &ALSA{l: l} }
|
||||||
|
|
||||||
// Name returns the name of the device.
|
// Name returns the name of the device.
|
||||||
func (d *ALSA) Name() string {
|
func (d *ALSA) Name() string {
|
||||||
|
@ -228,20 +221,20 @@ func (d *ALSA) Stop() error {
|
||||||
func (d *ALSA) open() error {
|
func (d *ALSA) open() error {
|
||||||
// Close any existing device.
|
// Close any existing device.
|
||||||
if d.dev != nil {
|
if d.dev != nil {
|
||||||
d.l.Log(logger.Debug, "closing device", "title", d.title)
|
d.l.Debug( "closing device", "title", d.title)
|
||||||
d.dev.Close()
|
d.dev.Close()
|
||||||
d.dev = nil
|
d.dev = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open sound card and open recording device.
|
// Open sound card and open recording device.
|
||||||
d.l.Log(logger.Debug, "opening sound card")
|
d.l.Debug( "opening sound card")
|
||||||
cards, err := yalsa.OpenCards()
|
cards, err := yalsa.OpenCards()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer yalsa.CloseCards(cards)
|
defer yalsa.CloseCards(cards)
|
||||||
|
|
||||||
d.l.Log(logger.Debug, "finding audio device")
|
d.l.Debug( "finding audio device")
|
||||||
for _, card := range cards {
|
for _, card := range cards {
|
||||||
devices, err := card.Devices()
|
devices, err := card.Devices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -261,7 +254,7 @@ func (d *ALSA) open() error {
|
||||||
return errors.New("no ALSA device found")
|
return errors.New("no ALSA device found")
|
||||||
}
|
}
|
||||||
|
|
||||||
d.l.Log(logger.Debug, "opening ALSA device", "title", d.dev.Title)
|
d.l.Debug( "opening ALSA device", "title", d.dev.Title)
|
||||||
err = d.dev.Open()
|
err = d.dev.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -270,13 +263,13 @@ func (d *ALSA) open() error {
|
||||||
// Try to configure device with chosen channels.
|
// Try to configure device with chosen channels.
|
||||||
channels, err := d.dev.NegotiateChannels(int(d.Channels))
|
channels, err := d.dev.NegotiateChannels(int(d.Channels))
|
||||||
if err != nil && d.Channels == 1 {
|
if err != nil && d.Channels == 1 {
|
||||||
d.l.Log(logger.Info, "device is unable to record in mono, trying stereo", "error", err)
|
d.l.Info( "device is unable to record in mono, trying stereo", "error", err)
|
||||||
channels, err = d.dev.NegotiateChannels(2)
|
channels, err = d.dev.NegotiateChannels(2)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("device is unable to record with requested number of channels: %w", err)
|
return fmt.Errorf("device is unable to record with requested number of channels: %w", err)
|
||||||
}
|
}
|
||||||
d.l.Log(logger.Debug, "alsa device channels set", "channels", channels)
|
d.l.Debug( "alsa device channels set", "channels", channels)
|
||||||
|
|
||||||
// Try to negotiate a rate to record in that is divisible by the wanted rate
|
// Try to negotiate a rate to record in that is divisible by the wanted rate
|
||||||
// so that it can be easily downsampled to the wanted rate.
|
// so that it can be easily downsampled to the wanted rate.
|
||||||
|
@ -296,7 +289,7 @@ func (d *ALSA) open() error {
|
||||||
rate, err = d.dev.NegotiateRate(r)
|
rate, err = d.dev.NegotiateRate(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
foundRate = true
|
foundRate = true
|
||||||
d.l.Log(logger.Debug, "alsa device sample rate set", "rate", rate)
|
d.l.Debug( "alsa device sample rate set", "rate", rate)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,12 +297,12 @@ func (d *ALSA) open() error {
|
||||||
|
|
||||||
// If no easily divisible rate is found, then use the default rate.
|
// If no easily divisible rate is found, then use the default rate.
|
||||||
if !foundRate {
|
if !foundRate {
|
||||||
d.l.Log(logger.Warning, "unable to sample at requested rate, default used.", "rateRequested", d.SampleRate)
|
d.l.Warning( "unable to sample at requested rate, default used.", "rateRequested", d.SampleRate)
|
||||||
rate, err = d.dev.NegotiateRate(defaultSampleRate)
|
rate, err = d.dev.NegotiateRate(defaultSampleRate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.l.Log(logger.Debug, "alsa device sample rate set", "rate", rate)
|
d.l.Debug( "alsa device sample rate set", "rate", rate)
|
||||||
}
|
}
|
||||||
|
|
||||||
var aFmt yalsa.FormatType
|
var aFmt yalsa.FormatType
|
||||||
|
@ -334,7 +327,7 @@ func (d *ALSA) open() error {
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported sample bits %v", d.BitDepth)
|
return fmt.Errorf("unsupported sample bits %v", d.BitDepth)
|
||||||
}
|
}
|
||||||
d.l.Log(logger.Debug, "alsa device bit depth set", "bitdepth", bitdepth)
|
d.l.Debug( "alsa device bit depth set", "bitdepth", bitdepth)
|
||||||
|
|
||||||
// A 50ms period is a sensible value for low-ish latency. (this could be made configurable if needed)
|
// A 50ms period is a sensible value for low-ish latency. (this could be made configurable if needed)
|
||||||
// Some devices only accept even period sizes while others want powers of 2.
|
// Some devices only accept even period sizes while others want powers of 2.
|
||||||
|
@ -349,13 +342,13 @@ func (d *ALSA) open() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.l.Log(logger.Debug, "alsa device buffer size set", "buffersize", bufSize)
|
d.l.Debug( "alsa device buffer size set", "buffersize", bufSize)
|
||||||
|
|
||||||
if err = d.dev.Prepare(); err != nil {
|
if err = d.dev.Prepare(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.l.Log(logger.Debug, "successfully negotiated device params")
|
d.l.Debug( "successfully negotiated device params")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,43 +366,43 @@ func (d *ALSA) input() {
|
||||||
continue
|
continue
|
||||||
case stopped:
|
case stopped:
|
||||||
if d.dev != nil {
|
if d.dev != nil {
|
||||||
d.l.Log(logger.Debug, "closing ALSA device", "title", d.title)
|
d.l.Debug( "closing ALSA device", "title", d.title)
|
||||||
d.dev.Close()
|
d.dev.Close()
|
||||||
d.dev = nil
|
d.dev = nil
|
||||||
}
|
}
|
||||||
err := d.buf.Close()
|
err := d.buf.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Error, "unable to close pool buffer", "error", err)
|
d.l.Error( "unable to close pool buffer", "error", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from audio device.
|
// Read from audio device.
|
||||||
d.l.Log(logger.Debug, "recording audio for period", "seconds", d.RecPeriod)
|
d.l.Debug( "recording audio for period", "seconds", d.RecPeriod)
|
||||||
err := d.dev.Read(d.pb.Data)
|
err := d.dev.Read(d.pb.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Debug, "read failed", "error", err.Error())
|
d.l.Debug( "read failed", "error", err.Error())
|
||||||
err = d.open() // re-open
|
err = d.open() // re-open
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Fatal, "reopening device failed", "error", err.Error())
|
d.l.Fatal( "reopening device failed", "error", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process audio.
|
// Process audio.
|
||||||
d.l.Log(logger.Debug, "processing audio")
|
d.l.Debug( "processing audio")
|
||||||
toWrite := d.formatBuffer()
|
toWrite := d.formatBuffer()
|
||||||
|
|
||||||
// Write audio to ringbuffer.
|
// Write audio to ringbuffer.
|
||||||
n, err := d.buf.Write(toWrite.Data)
|
n, err := d.buf.Write(toWrite.Data)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
d.l.Log(logger.Debug, "wrote audio to ringbuffer", "length", n)
|
d.l.Debug( "wrote audio to ringbuffer", "length", n)
|
||||||
case pool.ErrDropped:
|
case pool.ErrDropped:
|
||||||
d.l.Log(logger.Warning, "old audio data overwritten")
|
d.l.Warning( "old audio data overwritten")
|
||||||
default:
|
default:
|
||||||
d.l.Log(logger.Error, "unexpected ringbuffer error", "error", err.Error())
|
d.l.Error( "unexpected ringbuffer error", "error", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,36 +410,36 @@ func (d *ALSA) input() {
|
||||||
// Read reads from the ringbuffer, returning the number of bytes read upon success.
|
// Read reads from the ringbuffer, returning the number of bytes read upon success.
|
||||||
func (d *ALSA) Read(p []byte) (int, error) {
|
func (d *ALSA) Read(p []byte) (int, error) {
|
||||||
// Ready ringbuffer for read.
|
// Ready ringbuffer for read.
|
||||||
d.l.Log(logger.Debug, pkg+"getting next chunk ready")
|
d.l.Debug( pkg+"getting next chunk ready")
|
||||||
_, err := d.buf.Next(rbNextTimeout)
|
_, err := d.buf.Next(rbNextTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
case io.EOF:
|
case io.EOF:
|
||||||
d.l.Log(logger.Debug, pkg+"EOF from Next")
|
d.l.Debug( pkg+"EOF from Next")
|
||||||
return 0, err
|
return 0, err
|
||||||
case pool.ErrTimeout:
|
case pool.ErrTimeout:
|
||||||
d.l.Log(logger.Debug, pkg+"pool buffer timeout")
|
d.l.Debug( pkg+"pool buffer timeout")
|
||||||
return 0, err
|
return 0, err
|
||||||
default:
|
default:
|
||||||
d.l.Log(logger.Error, pkg+"unexpected error from Next", "error", err.Error())
|
d.l.Error( pkg+"unexpected error from Next", "error", err.Error())
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from pool buffer.
|
// Read from pool buffer.
|
||||||
d.l.Log(logger.Debug, pkg+"reading from buffer")
|
d.l.Debug( pkg+"reading from buffer")
|
||||||
n, err := d.buf.Read(p)
|
n, err := d.buf.Read(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
case io.EOF:
|
case io.EOF:
|
||||||
d.l.Log(logger.Debug, pkg+"EOF from Read")
|
d.l.Debug( pkg+"EOF from Read")
|
||||||
return n, err
|
return n, err
|
||||||
default:
|
default:
|
||||||
d.l.Log(logger.Error, pkg+"unexpected error from Read", "error", err.Error())
|
d.l.Error( pkg+"unexpected error from Read", "error", err.Error())
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.l.Log(logger.Debug, fmt.Sprintf("%v read %v bytes", pkg, n))
|
d.l.Debug( fmt.Sprintf("%v read %v bytes", pkg, n))
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +458,7 @@ func (d *ALSA) formatBuffer() pcm.Buffer {
|
||||||
if d.pb.Format.Channels == 2 && d.Channels == 1 {
|
if d.pb.Format.Channels == 2 && d.Channels == 1 {
|
||||||
formatted, err = pcm.StereoToMono(d.pb)
|
formatted, err = pcm.StereoToMono(d.pb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Fatal, "channel conversion failed", "error", err.Error())
|
d.l.Fatal( "channel conversion failed", "error", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,7 +467,7 @@ func (d *ALSA) formatBuffer() pcm.Buffer {
|
||||||
// Convert rate.
|
// Convert rate.
|
||||||
formatted, err = pcm.Resample(formatted, d.SampleRate)
|
formatted, err = pcm.Resample(formatted, d.SampleRate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Fatal, "rate conversion failed", "error", err.Error())
|
d.l.Fatal( "rate conversion failed", "error", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,11 +478,11 @@ func (d *ALSA) formatBuffer() pcm.Buffer {
|
||||||
enc := adpcm.NewEncoder(b)
|
enc := adpcm.NewEncoder(b)
|
||||||
_, err = enc.Write(formatted.Data)
|
_, err = enc.Write(formatted.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Fatal, "unable to encode", "error", err.Error())
|
d.l.Fatal( "unable to encode", "error", err.Error())
|
||||||
}
|
}
|
||||||
formatted.Data = b.Bytes()
|
formatted.Data = b.Bytes()
|
||||||
default:
|
default:
|
||||||
d.l.Log(logger.Error, "unhandled audio codec")
|
d.l.Error( "unhandled audio codec")
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatted
|
return formatted
|
||||||
|
|
|
@ -36,7 +36,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/av/device"
|
"bitbucket.org/ausocean/av/device"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDevice(t *testing.T) {
|
func TestDevice(t *testing.T) {
|
||||||
|
@ -51,7 +51,7 @@ func TestDevice(t *testing.T) {
|
||||||
n := 2 // Number of periods to wait while recording.
|
n := 2 // Number of periods to wait while recording.
|
||||||
|
|
||||||
// Create a new ALSA device, start, read/lex, and then stop it.
|
// Create a new ALSA device, start, read/lex, and then stop it.
|
||||||
l := logger.New(logger.Debug, os.Stderr, true)
|
l := logging.New(logging.Debug, os.Stderr, true)
|
||||||
ai := New(l)
|
ai := New(l)
|
||||||
err := ai.Setup(c)
|
err := ai.Setup(c)
|
||||||
// Log any config errors, otherwise if there was an error opening a device, skip
|
// Log any config errors, otherwise if there was an error opening a device, skip
|
||||||
|
@ -121,7 +121,7 @@ func TestIsRunning(t *testing.T) {
|
||||||
const bitDepth = 16
|
const bitDepth = 16
|
||||||
const recPeriod = 1
|
const recPeriod = 1
|
||||||
|
|
||||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
l := logging.New(logging.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||||
d := New(l)
|
d := New(l)
|
||||||
|
|
||||||
err := d.Setup(config.Config{
|
err := d.Setup(config.Config{
|
||||||
|
|
|
@ -42,7 +42,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/protocol/rtp"
|
"bitbucket.org/ausocean/av/protocol/rtp"
|
||||||
"bitbucket.org/ausocean/av/protocol/rtsp"
|
"bitbucket.org/ausocean/av/protocol/rtsp"
|
||||||
avconfig "bitbucket.org/ausocean/av/revid/config"
|
avconfig "bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"bitbucket.org/ausocean/utils/sliceutils"
|
"bitbucket.org/ausocean/utils/sliceutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ var (
|
||||||
// Any other models are untested.
|
// Any other models are untested.
|
||||||
type GeoVision struct {
|
type GeoVision struct {
|
||||||
cfg avconfig.Config
|
cfg avconfig.Config
|
||||||
log avconfig.Logger
|
log logging.Logger
|
||||||
rtpClt *rtp.Client
|
rtpClt *rtp.Client
|
||||||
rtspClt *rtsp.Client
|
rtspClt *rtsp.Client
|
||||||
rtcpClt *rtcp.Client
|
rtcpClt *rtcp.Client
|
||||||
|
@ -99,7 +99,7 @@ type GeoVision struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGeoVision returns a new GeoVision.
|
// NewGeoVision returns a new GeoVision.
|
||||||
func New(l avconfig.Logger) *GeoVision { return &GeoVision{log: l} }
|
func New(l logging.Logger) *GeoVision { return &GeoVision{log: l} }
|
||||||
|
|
||||||
// Name returns the name of the device.
|
// Name returns the name of the device.
|
||||||
func (g *GeoVision) Name() string {
|
func (g *GeoVision) Name() string {
|
||||||
|
@ -223,32 +223,32 @@ func (g *GeoVision) Start() error {
|
||||||
return fmt.Errorf("could not create RTSP client: %w", err)
|
return fmt.Errorf("could not create RTSP client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.log.Log(logger.Info, pkg+"created RTSP client")
|
g.log.Info(pkg + "created RTSP client")
|
||||||
|
|
||||||
resp, err := g.rtspClt.Options()
|
resp, err := g.rtspClt.Options()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("options request unsuccessful: %w", err)
|
return fmt.Errorf("options request unsuccessful: %w", err)
|
||||||
}
|
}
|
||||||
g.log.Log(logger.Debug, pkg+"RTSP OPTIONS response", "response", resp.String())
|
g.log.Debug(pkg+"RTSP OPTIONS response", "response", resp.String())
|
||||||
|
|
||||||
resp, err = g.rtspClt.Describe()
|
resp, err = g.rtspClt.Describe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("describe request unsuccessful: %w", err)
|
return fmt.Errorf("describe request unsuccessful: %w", err)
|
||||||
}
|
}
|
||||||
g.log.Log(logger.Debug, pkg+"RTSP DESCRIBE response", "response", resp.String())
|
g.log.Debug(pkg+"RTSP DESCRIBE response", "response", resp.String())
|
||||||
|
|
||||||
resp, err = g.rtspClt.Setup("track1", fmt.Sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPort, rtcpPort))
|
resp, err = g.rtspClt.Setup("track1", fmt.Sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPort, rtcpPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("setup request unsuccessful: %w", err)
|
return fmt.Errorf("setup request unsuccessful: %w", err)
|
||||||
}
|
}
|
||||||
g.log.Log(logger.Debug, pkg+"RTSP SETUP response", "response", resp.String())
|
g.log.Debug(pkg+"RTSP SETUP response", "response", resp.String())
|
||||||
|
|
||||||
rtpCltAddr, rtcpCltAddr, rtcpSvrAddr, err := formAddrs(local, remote, *resp)
|
rtpCltAddr, rtcpCltAddr, rtcpSvrAddr, err := formAddrs(local, remote, *resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not format addresses: %w", err)
|
return fmt.Errorf("could not format addresses: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.log.Log(logger.Info, pkg+"RTSP session setup complete")
|
g.log.Info(pkg + "RTSP session setup complete")
|
||||||
|
|
||||||
g.rtpClt, err = rtp.NewClient(rtpCltAddr)
|
g.rtpClt, err = rtp.NewClient(rtpCltAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -260,14 +260,14 @@ func (g *GeoVision) Start() error {
|
||||||
return fmt.Errorf("could not create RTCP client: %w", err)
|
return fmt.Errorf("could not create RTCP client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.log.Log(logger.Info, pkg+"RTCP and RTP clients created")
|
g.log.Info(pkg + "RTCP and RTP clients created")
|
||||||
|
|
||||||
// Check errors from RTCP client until it has stopped running.
|
// Check errors from RTCP client until it has stopped running.
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
err, ok := <-g.rtcpClt.Err()
|
err, ok := <-g.rtcpClt.Err()
|
||||||
if ok {
|
if ok {
|
||||||
g.log.Log(logger.Warning, pkg+"RTCP error", "error", err.Error())
|
g.log.Warning(pkg+"RTCP error", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -276,14 +276,14 @@ func (g *GeoVision) Start() error {
|
||||||
|
|
||||||
// Start the RTCP client.
|
// Start the RTCP client.
|
||||||
g.rtcpClt.Start()
|
g.rtcpClt.Start()
|
||||||
g.log.Log(logger.Info, pkg+"RTCP client started")
|
g.log.Info(pkg + "RTCP client started")
|
||||||
|
|
||||||
resp, err = g.rtspClt.Play()
|
resp, err = g.rtspClt.Play()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("play request unsuccessful: %w", err)
|
return fmt.Errorf("play request unsuccessful: %w", err)
|
||||||
}
|
}
|
||||||
g.log.Log(logger.Debug, pkg+"RTSP server PLAY response", "response", resp.String())
|
g.log.Debug(pkg+"RTSP server PLAY response", "response", resp.String())
|
||||||
g.log.Log(logger.Info, pkg+"play requested, now receiving stream")
|
g.log.Info(pkg + "play requested, now receiving stream")
|
||||||
g.isRunning = true
|
g.isRunning = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -304,7 +304,7 @@ func (g *GeoVision) Stop() error {
|
||||||
|
|
||||||
g.rtcpClt.Stop()
|
g.rtcpClt.Stop()
|
||||||
|
|
||||||
g.log.Log(logger.Info, pkg+"RTP, RTSP and RTCP clients stopped and closed")
|
g.log.Info(pkg + "RTP, RTSP and RTCP clients stopped and closed")
|
||||||
|
|
||||||
g.isRunning = false
|
g.isRunning = false
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,14 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsRunning(t *testing.T) {
|
func TestIsRunning(t *testing.T) {
|
||||||
const dur = 250 * time.Millisecond
|
const dur = 250 * time.Millisecond
|
||||||
const ip = "192.168.4.20"
|
const ip = "192.168.4.20"
|
||||||
|
|
||||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
l := logging.New(logging.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||||
d := New(l)
|
d := New(l)
|
||||||
|
|
||||||
err := d.Set(config.Config{
|
err := d.Set(config.Config{
|
||||||
|
|
|
@ -38,18 +38,19 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type raspistill struct {
|
type raspistill struct {
|
||||||
cfg config.Config
|
cfg config.Config
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
out io.ReadCloser
|
out io.ReadCloser
|
||||||
log config.Logger
|
log logging.Logger
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
isRunning bool
|
isRunning bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func new(l config.Logger) raspistill {
|
func new(l logging.Logger) raspistill {
|
||||||
return raspistill{
|
return raspistill{
|
||||||
log: l,
|
log: l,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
|
|
|
@ -53,7 +53,7 @@ type raspistill struct {
|
||||||
imgCnt int // Number of images that have been loaded thus far.
|
imgCnt int // Number of images that have been loaded thus far.
|
||||||
durTicker *time.Ticker // Tracks timelapse duration.
|
durTicker *time.Ticker // Tracks timelapse duration.
|
||||||
intvlTicker *time.Ticker // Tracks current interval in the timelapse.
|
intvlTicker *time.Ticker // Tracks current interval in the timelapse.
|
||||||
log config.Logger
|
log logging.Logger
|
||||||
cfg config.Config
|
cfg config.Config
|
||||||
isRunning bool
|
isRunning bool
|
||||||
buf []byte // Holds frame data to be read.
|
buf []byte // Holds frame data to be read.
|
||||||
|
@ -61,7 +61,7 @@ type raspistill struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func new(l config.Logger) raspistill {
|
func new(l logging.Logger) raspistill {
|
||||||
l.Debug("creating new test raspistill input")
|
l.Debug("creating new test raspistill input")
|
||||||
|
|
||||||
r := raspistill{log: l}
|
r := raspistill{log: l}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/device"
|
"bitbucket.org/ausocean/av/device"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// To indicate package when logging.
|
// To indicate package when logging.
|
||||||
|
@ -78,7 +79,7 @@ var errNotStarted = errors.New("cannot read, raspistill not started")
|
||||||
type Raspistill struct{ raspistill }
|
type Raspistill struct{ raspistill }
|
||||||
|
|
||||||
// New returns a new Raspistill.
|
// New returns a new Raspistill.
|
||||||
func New(l config.Logger) *Raspistill { return &Raspistill{raspistill: new(l)} }
|
func New(l logging.Logger) *Raspistill { return &Raspistill{raspistill: new(l)} }
|
||||||
|
|
||||||
// Start will prepare the arguments for the raspistill command using the
|
// Start will prepare the arguments for the raspistill command using the
|
||||||
// configuration set using the Set method then call the raspistill command,
|
// configuration set using the Set method then call the raspistill command,
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/av/device"
|
"bitbucket.org/ausocean/av/device"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"bitbucket.org/ausocean/utils/sliceutils"
|
"bitbucket.org/ausocean/utils/sliceutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -124,13 +124,13 @@ type Raspivid struct {
|
||||||
cfg config.Config
|
cfg config.Config
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
out io.ReadCloser
|
out io.ReadCloser
|
||||||
log config.Logger
|
log logging.Logger
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
isRunning bool
|
isRunning bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Raspivid.
|
// New returns a new Raspivid.
|
||||||
func New(l config.Logger) *Raspivid {
|
func New(l logging.Logger) *Raspivid {
|
||||||
return &Raspivid{
|
return &Raspivid{
|
||||||
log: l,
|
log: l,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
|
@ -277,7 +277,7 @@ func (r *Raspivid) Start() error {
|
||||||
return fmt.Errorf("could not create raspivid args: %w", err)
|
return fmt.Errorf("could not create raspivid args: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Info, pkg+"raspivid args", "raspividArgs", strings.Join(args, " "))
|
r.cfg.Logger.Info( pkg+"raspivid args", "raspividArgs", strings.Join(args, " "))
|
||||||
r.cmd = exec.Command("raspivid", args...)
|
r.cmd = exec.Command("raspivid", args...)
|
||||||
|
|
||||||
r.out, err = r.cmd.StdoutPipe()
|
r.out, err = r.cmd.StdoutPipe()
|
||||||
|
@ -294,17 +294,17 @@ func (r *Raspivid) Start() error {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-r.done:
|
case <-r.done:
|
||||||
r.cfg.Logger.Log(logger.Info, "raspivid.Stop() called, finished checking stderr")
|
r.cfg.Logger.Info( "raspivid.Stop() called, finished checking stderr")
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
buf, err := ioutil.ReadAll(stderr)
|
buf, err := ioutil.ReadAll(stderr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Error, "could not read stderr", "error", err)
|
r.cfg.Logger.Error( "could not read stderr", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) != 0 {
|
if len(buf) != 0 {
|
||||||
r.cfg.Logger.Log(logger.Error, "error from raspivid stderr", "error", string(buf))
|
r.cfg.Logger.Error( "error from raspivid stderr", "error", string(buf))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,13 +31,13 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsRunning(t *testing.T) {
|
func TestIsRunning(t *testing.T) {
|
||||||
const dur = 250 * time.Millisecond
|
const dur = 250 * time.Millisecond
|
||||||
|
|
||||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
l := logging.New(logging.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||||
d := New(l)
|
d := New(l)
|
||||||
|
|
||||||
err := d.Set(config.Config{
|
err := d.Set(config.Config{
|
||||||
|
|
|
@ -36,7 +36,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/av/device"
|
"bitbucket.org/ausocean/av/device"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used to indicate package in logging.
|
// Used to indicate package in logging.
|
||||||
|
@ -64,7 +64,7 @@ var (
|
||||||
// uses an ffmpeg process to pipe the video data from the webcam.
|
// uses an ffmpeg process to pipe the video data from the webcam.
|
||||||
type Webcam struct {
|
type Webcam struct {
|
||||||
out io.ReadCloser
|
out io.ReadCloser
|
||||||
log config.Logger
|
log logging.Logger
|
||||||
cfg config.Config
|
cfg config.Config
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
|
@ -72,7 +72,7 @@ type Webcam struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Webcam.
|
// New returns a new Webcam.
|
||||||
func New(l config.Logger) *Webcam {
|
func New(l logging.Logger) *Webcam {
|
||||||
return &Webcam{
|
return &Webcam{
|
||||||
log: l,
|
log: l,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
|
@ -152,7 +152,7 @@ func (w *Webcam) Start() error {
|
||||||
"-",
|
"-",
|
||||||
)
|
)
|
||||||
|
|
||||||
w.log.Log(logger.Info, pkg+"ffmpeg args", "args", strings.Join(args, " "))
|
w.log.Info( pkg+"ffmpeg args", "args", strings.Join(args, " "))
|
||||||
w.cmd = exec.Command("ffmpeg", args...)
|
w.cmd = exec.Command("ffmpeg", args...)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -172,29 +172,29 @@ func (w *Webcam) Start() error {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
w.cfg.Logger.Log(logger.Info, "webcam.Stop() called, finished checking stderr")
|
w.cfg.Logger.Info( "webcam.Stop() called, finished checking stderr")
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
buf, err := ioutil.ReadAll(stderr)
|
buf, err := ioutil.ReadAll(stderr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.cfg.Logger.Log(logger.Error, "could not read stderr", "error", err)
|
w.cfg.Logger.Error( "could not read stderr", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) != 0 {
|
if len(buf) != 0 {
|
||||||
w.cfg.Logger.Log(logger.Error, "error from webcam stderr", "error", string(buf))
|
w.cfg.Logger.Error( "error from webcam stderr", "error", string(buf))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
w.cfg.Logger.Log(logger.Info, "starting webcam")
|
w.cfg.Logger.Info( "starting webcam")
|
||||||
err = w.cmd.Start()
|
err = w.cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to start ffmpeg: %w", err)
|
return fmt.Errorf("failed to start ffmpeg: %w", err)
|
||||||
}
|
}
|
||||||
w.cfg.Logger.Log(logger.Info, "webcam started")
|
w.cfg.Logger.Info( "webcam started")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,13 +31,13 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsRunning(t *testing.T) {
|
func TestIsRunning(t *testing.T) {
|
||||||
const dur = 250 * time.Millisecond
|
const dur = 250 * time.Millisecond
|
||||||
|
|
||||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
l := logging.New(logging.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||||
d := New(l)
|
d := New(l)
|
||||||
|
|
||||||
err := d.Set(config.Config{
|
err := d.Set(config.Config{
|
||||||
|
|
|
@ -69,7 +69,7 @@ import (
|
||||||
"bitbucket.org/ausocean/av/revid"
|
"bitbucket.org/ausocean/av/revid"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Copyright information prefixed to all metadata.
|
// Copyright information prefixed to all metadata.
|
||||||
|
@ -80,7 +80,7 @@ const (
|
||||||
|
|
||||||
// Logging configuration.
|
// Logging configuration.
|
||||||
const (
|
const (
|
||||||
logLevel = logger.Info
|
logLevel = logging.Info
|
||||||
logSuppress = true
|
logSuppress = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -110,13 +110,13 @@ const (
|
||||||
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 logging.Logger
|
||||||
|
|
||||||
// stdoutLogger provides an io.Writer for the purpose of capturing stdout from
|
// 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
|
// the VLC process and using the logger to capture and print to stdout of
|
||||||
// this process.
|
// this process.
|
||||||
type stdoutLogger struct {
|
type stdoutLogger struct {
|
||||||
l *logger.Logger
|
l logging.Logger
|
||||||
t string
|
t string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ func (sl *stdoutLogger) Write(d []byte) (int, error) {
|
||||||
// the VLC process and using the logger to capture and print to stdout of
|
// the VLC process and using the logger to capture and print to stdout of
|
||||||
// this process.
|
// this process.
|
||||||
type stderrLogger struct {
|
type stderrLogger struct {
|
||||||
l *logger.Logger
|
l logging.Logger
|
||||||
t string
|
t string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ func main() {
|
||||||
// Create logger that methods will be called on by the netsender client and
|
// 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
|
// revid to log messages. Logs will go the lumberjack logger to handle file
|
||||||
// writing of messages.
|
// writing of messages.
|
||||||
log = logger.New(
|
log = logging.New(
|
||||||
logLevel,
|
logLevel,
|
||||||
os.Stdout,
|
os.Stdout,
|
||||||
logSuppress,
|
logSuppress,
|
||||||
|
@ -253,9 +253,9 @@ func main() {
|
||||||
func profile() {
|
func profile() {
|
||||||
f, err := os.Create(profilePath)
|
f, err := os.Create(profilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Fatal, pkg+"could not create CPU profile", "error", err.Error())
|
log.Fatal( pkg+"could not create CPU profile", "error", err.Error())
|
||||||
}
|
}
|
||||||
if err := pprof.StartCPUProfile(f); err != nil {
|
if err := pprof.StartCPUProfile(f); err != nil {
|
||||||
log.Log(logger.Fatal, pkg+"could not start CPU profile", "error", err.Error())
|
log.Fatal( pkg+"could not start CPU profile", "error", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const downscale = 1
|
const downscale = 1
|
||||||
|
@ -40,7 +40,7 @@ func (d *dumbWriteCloser) Write(p []byte) (int, error) { return len(p), nil }
|
||||||
func (d *dumbWriteCloser) Close() error { return nil }
|
func (d *dumbWriteCloser) Close() error { return nil }
|
||||||
|
|
||||||
func BenchmarkBasic(b *testing.B) {
|
func BenchmarkBasic(b *testing.B) {
|
||||||
cfg := config.Config{Logger: logger.New(logger.Debug, &bytes.Buffer{}, true)}
|
cfg := config.Config{Logger: logging.New(logging.Debug, &bytes.Buffer{}, true)}
|
||||||
err := cfg.Validate()
|
err := cfg.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("config struct is bad: %v#", err)
|
b.Fatalf("config struct is bad: %v#", err)
|
||||||
|
@ -60,7 +60,7 @@ func BenchmarkBasic(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDifference(b *testing.B) {
|
func BenchmarkDifference(b *testing.B) {
|
||||||
cfg := config.Config{Logger: logger.New(logger.Debug, &bytes.Buffer{}, true)}
|
cfg := config.Config{Logger: logging.New(logging.Debug, &bytes.Buffer{}, true)}
|
||||||
err := cfg.Validate()
|
err := cfg.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("config struct is bad: %v#", err)
|
b.Fatalf("config struct is bad: %v#", err)
|
||||||
|
@ -80,7 +80,7 @@ func BenchmarkDifference(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkKNN(b *testing.B) {
|
func BenchmarkKNN(b *testing.B) {
|
||||||
cfg := config.Config{Logger: logger.New(logger.Debug, &bytes.Buffer{}, true), MotionDownscaling: downscale}
|
cfg := config.Config{Logger: logging.New(logging.Debug, &bytes.Buffer{}, true), MotionDownscaling: downscale}
|
||||||
err := cfg.Validate()
|
err := cfg.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("config struct is bad: %v#", err)
|
b.Fatalf("config struct is bad: %v#", err)
|
||||||
|
@ -100,7 +100,7 @@ func BenchmarkKNN(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMOG(b *testing.B) {
|
func BenchmarkMOG(b *testing.B) {
|
||||||
cfg := config.Config{Logger: logger.New(logger.Debug, &bytes.Buffer{}, true), MotionDownscaling: downscale}
|
cfg := config.Config{Logger: logging.New(logging.Debug, &bytes.Buffer{}, true), MotionDownscaling: downscale}
|
||||||
err := cfg.Validate()
|
err := cfg.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("config struct is bad: %v#", err)
|
b.Fatalf("config struct is bad: %v#", err)
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -3,8 +3,8 @@ module bitbucket.org/ausocean/av
|
||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
bitbucket.org/ausocean/iot v1.3.1
|
bitbucket.org/ausocean/iot v1.3.2
|
||||||
bitbucket.org/ausocean/utils v1.2.17
|
bitbucket.org/ausocean/utils v1.3.1
|
||||||
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
|
||||||
|
|
30
go.sum
30
go.sum
|
@ -1,9 +1,10 @@
|
||||||
bitbucket.org/ausocean/iot v1.3.0/go.mod h1:rRcWt6SoM/jgIZpP1zrpnKb5BhxIMulAJ+q1xTvLh94=
|
bitbucket.org/ausocean/iot v1.3.0/go.mod h1:rRcWt6SoM/jgIZpP1zrpnKb5BhxIMulAJ+q1xTvLh94=
|
||||||
bitbucket.org/ausocean/iot v1.3.1 h1:TAofuRw8w6S+F1u8bzk5RojnyGeAS6PFZl9PvfzeFh8=
|
bitbucket.org/ausocean/iot v1.3.2 h1:aMLIipH4GT8ItrHTlFh/cwEbGxsp0fkGhvFZy3zP3KI=
|
||||||
bitbucket.org/ausocean/iot v1.3.1/go.mod h1:ttXSiDO1kr8KLo46q/cZEyaBgPBuKqu90Mnv4oqkHBo=
|
bitbucket.org/ausocean/iot v1.3.2/go.mod h1:NbEg2PvYSHDdUsy5eMmihBySpWfqaHiMdspQDZdDe8o=
|
||||||
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.17 h1:6ZqXvxRXHHL18s2kn22E2/AORNn2WsgQXcEnctWwvrk=
|
bitbucket.org/ausocean/utils v1.3.0/go.mod h1:yWsulKjbBgwL17/w55MQ6cIT9jmNeOkwpd2gUIxAcIY=
|
||||||
bitbucket.org/ausocean/utils v1.2.17/go.mod h1:uoIRyy4jwH0/9b/t9tfPuV9Vl14AONeILw9KimUISYg=
|
bitbucket.org/ausocean/utils v1.3.1 h1:xESAyWsq2tExr8uNPqpysBAgihTJVoLYLF77ABZjX4g=
|
||||||
|
bitbucket.org/ausocean/utils v1.3.1/go.mod h1:XgvCH4DQLCd6NYMzsSqwhHmPr+qzYks5M8IDpdNnZiU=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
|
@ -14,6 +15,7 @@ github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7/go.mod h1:O5HA0jgDXkB
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/adrianmo/go-nmea v1.1.1-0.20190109062325-c448653979f7/go.mod h1:HHPxPAm2kmev+61qmkZh7xgZF/7qHtSpsWppip2Ipv8=
|
github.com/adrianmo/go-nmea v1.1.1-0.20190109062325-c448653979f7/go.mod h1:HHPxPAm2kmev+61qmkZh7xgZF/7qHtSpsWppip2Ipv8=
|
||||||
|
github.com/aerth/playwav v0.0.0-20170324024803-17dfe21a406f/go.mod h1:aTANbm/GXj1ilCRMsIiSpX0i7LUkqjAPj6R0fpWbLNA=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527 h1:NImof/JkF93OVWZY+PINgl6fPtQyF6f+hNUtZ0QZA1c=
|
github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527 h1:NImof/JkF93OVWZY+PINgl6fPtQyF6f+hNUtZ0QZA1c=
|
||||||
github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
|
@ -21,6 +23,13 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNg
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
|
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
|
||||||
|
github.com/cocoonlife/goalsa v0.0.0-20160812085113-b711ae6f3eff/go.mod h1:5aLO409bJnd+jCw0t/SB/DhHkVBhPAE31lnHJnYQxy0=
|
||||||
|
github.com/cocoonlife/testify v0.0.0-20160218172820-792cc1faeb64/go.mod h1:LoCAz53rbPcqs8Da2BjB/yDy4gxMtiSQmqnYI/DGH+U=
|
||||||
|
github.com/cryptix/wav v0.0.0-20180415113528-8bdace674401/go.mod h1:knK8fd+KPlGGqSUWogv1DQzGTwnfUvAi0cIoWyOG7+U=
|
||||||
|
github.com/d2r2/go-dht v0.0.0-20200119175940-4ba96621a218/go.mod h1:AzSqP4S4/6pINOKg3VC79WC7YY3zskQcrXMFzphCry0=
|
||||||
|
github.com/d2r2/go-logger v0.0.0-20210606094344-60e9d1233e22/go.mod h1:eSx+YfcVy5vCjRZBNIhpIpfCGFMQ6XSOSQkDk7+VCpg=
|
||||||
|
github.com/d2r2/go-shell v0.0.0-20211022052110-f591c27e3e2e/go.mod h1:yqtlOXB0bWzWgM4wZ9BdZ75OmXSiFYSKrZ3TZlPaePQ=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -47,19 +56,20 @@ github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2
|
||||||
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
|
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
|
||||||
github.com/go-pdf/fpdf v0.5.0 h1:GHpcYsiDV2hdo77VTOuTF9k1sN8F8IY7NjnCo9x+NPY=
|
github.com/go-pdf/fpdf v0.5.0 h1:GHpcYsiDV2hdo77VTOuTF9k1sN8F8IY7NjnCo9x+NPY=
|
||||||
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||||
|
github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
|
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
|
||||||
github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs=
|
github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs=
|
||||||
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4/go.mod h1:2RvX5ZjVtsznNZPEt4xwJXNJrM3VTZoQf7V6gk0ysvs=
|
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4/go.mod h1:2RvX5ZjVtsznNZPEt4xwJXNJrM3VTZoQf7V6gk0ysvs=
|
||||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/kidoman/embd v0.0.0-20170508013040-d3d8c0c5c68d h1:dPUSr0RGzXAdsUTMtiyQ/2RBLIIwkv6jGnhxrufitvQ=
|
github.com/kidoman/embd v0.0.0-20170508013040-d3d8c0c5c68d h1:dPUSr0RGzXAdsUTMtiyQ/2RBLIIwkv6jGnhxrufitvQ=
|
||||||
github.com/kidoman/embd v0.0.0-20170508013040-d3d8c0c5c68d/go.mod h1:ACKj9jnzOzj1lw2ETilpFGK7L9dtJhAzT7T1OhAGtRQ=
|
github.com/kidoman/embd v0.0.0-20170508013040-d3d8c0c5c68d/go.mod h1:ACKj9jnzOzj1lw2ETilpFGK7L9dtJhAzT7T1OhAGtRQ=
|
||||||
|
github.com/kortschak/nmea v0.0.0-20210407203620-e8c5d9a5a0ec/go.mod h1:Vq0wW4Bqk5w3PLk4LUj0l5FkMM1Rbrhvlzo3cJl7I5s=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
@ -80,12 +90,13 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF
|
||||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
|
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||||
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e h1:3NIzz7weXhh3NToPgbtlQtKiVgerEaG4/nY2skGoGG0=
|
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e h1:3NIzz7weXhh3NToPgbtlQtKiVgerEaG4/nY2skGoGG0=
|
||||||
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e/go.mod h1:CaowXBWOiSGWEpBBV8LoVnQTVPV4ycyviC9IBLj8dRw=
|
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e/go.mod h1:CaowXBWOiSGWEpBBV8LoVnQTVPV4ycyviC9IBLj8dRw=
|
||||||
github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624/go.mod h1:MqFju5qeLDFh+S9PqxYT7TEla8xeW7bgGr/69q3oki0=
|
github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624/go.mod h1:MqFju5qeLDFh+S9PqxYT7TEla8xeW7bgGr/69q3oki0=
|
||||||
|
@ -100,6 +111,7 @@ gocv.io/x/gocv v0.29.0 h1:Zg5ZoIFSY4oBehoIRoSaSeY+KF+nvqv1O1qNmALiMec=
|
||||||
gocv.io/x/gocv v0.29.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU=
|
gocv.io/x/gocv v0.29.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -123,13 +135,14 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -161,7 +174,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
|
rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/protocol/rtp"
|
"bitbucket.org/ausocean/av/protocol/rtp"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -120,7 +120,7 @@ func (c *Client) SetName(name string) {
|
||||||
// receiving and parsing sender reports, and the process of sending receiver
|
// receiving and parsing sender reports, and the process of sending receiver
|
||||||
// reports to the server.
|
// reports to the server.
|
||||||
func (c *Client) Start() {
|
func (c *Client) Start() {
|
||||||
c.log(logger.Debug, pkg+"Client is starting")
|
c.log(logging.Debug, pkg+"Client is starting")
|
||||||
c.wg.Add(2)
|
c.wg.Add(2)
|
||||||
go c.recv()
|
go c.recv()
|
||||||
go c.send()
|
go c.send()
|
||||||
|
@ -129,7 +129,7 @@ func (c *Client) Start() {
|
||||||
// Stop sends a quit signal to the send and receive routines and closes the
|
// Stop sends a quit signal to the send and receive routines and closes the
|
||||||
// UDP connection. It will wait until both routines have returned.
|
// UDP connection. It will wait until both routines have returned.
|
||||||
func (c *Client) Stop() {
|
func (c *Client) Stop() {
|
||||||
c.log(logger.Debug, pkg+"Client is stopping")
|
c.log(logging.Debug, pkg+"Client is stopping")
|
||||||
close(c.quit)
|
close(c.quit)
|
||||||
c.conn.Close()
|
c.conn.Close()
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
|
@ -145,7 +145,7 @@ func (c *Client) Err() <-chan error {
|
||||||
// recv reads from the UDP connection and parses SenderReports.
|
// recv reads from the UDP connection and parses SenderReports.
|
||||||
func (c *Client) recv() {
|
func (c *Client) recv() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
c.log(logger.Debug, pkg+"Client is receiving")
|
c.log(logging.Debug, pkg+"Client is receiving")
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -157,7 +157,7 @@ func (c *Client) recv() {
|
||||||
c.err <- err
|
c.err <- err
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.log(logger.Debug, pkg+"sender report received", "report", buf[:n])
|
c.log(logging.Debug, pkg+"sender report received", "report", buf[:n])
|
||||||
c.parse(buf[:n])
|
c.parse(buf[:n])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ func (c *Client) recv() {
|
||||||
// send writes receiver reports to the server.
|
// send writes receiver reports to the server.
|
||||||
func (c *Client) send() {
|
func (c *Client) send() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
c.log(logger.Debug, pkg+"Client is sending")
|
c.log(logging.Debug, pkg+"Client is sending")
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c.quit:
|
case <-c.quit:
|
||||||
|
@ -216,7 +216,7 @@ func (c *Client) send() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log(logger.Debug, pkg+"sending receiver report")
|
c.log(logging.Debug, pkg+"sending receiver report")
|
||||||
_, err := c.conn.Write(c.formPayload(&report, &description))
|
_, err := c.conn.Write(c.formPayload(&report, &description))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.err <- err
|
c.err <- err
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/protocol/rtp"
|
"bitbucket.org/ausocean/av/protocol/rtp"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestFromPayload checks that formPayload is working as expected.
|
// TestFromPayload checks that formPayload is working as expected.
|
||||||
|
@ -122,15 +122,15 @@ type dummyLogger testing.T
|
||||||
func (dl *dummyLogger) log(lvl int8, msg string, args ...interface{}) {
|
func (dl *dummyLogger) log(lvl int8, msg string, args ...interface{}) {
|
||||||
var l string
|
var l string
|
||||||
switch lvl {
|
switch lvl {
|
||||||
case logger.Warning:
|
case logging.Warning:
|
||||||
l = "warning"
|
l = "warning"
|
||||||
case logger.Debug:
|
case logging.Debug:
|
||||||
l = "debug"
|
l = "debug"
|
||||||
case logger.Info:
|
case logging.Info:
|
||||||
l = "info"
|
l = "info"
|
||||||
case logger.Error:
|
case logging.Error:
|
||||||
l = "error"
|
l = "error"
|
||||||
case logger.Fatal:
|
case logging.Fatal:
|
||||||
l = "fatal"
|
l = "fatal"
|
||||||
}
|
}
|
||||||
msg = l + ": " + msg
|
msg = l + ": " + msg
|
||||||
|
|
|
@ -33,7 +33,6 @@ import (
|
||||||
"bitbucket.org/ausocean/av/container/mts"
|
"bitbucket.org/ausocean/av/container/mts"
|
||||||
"bitbucket.org/ausocean/av/device"
|
"bitbucket.org/ausocean/av/device"
|
||||||
"bitbucket.org/ausocean/av/device/alsa"
|
"bitbucket.org/ausocean/av/device/alsa"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used to reliably read, write, and test audio metadata entry keys.
|
// Used to reliably read, write, and test audio metadata entry keys.
|
||||||
|
@ -51,17 +50,17 @@ func (r *Revid) setupAudio() error {
|
||||||
r.input = d
|
r.input = d
|
||||||
|
|
||||||
// Configure ALSA device.
|
// Configure ALSA device.
|
||||||
r.cfg.Logger.Log(logger.Debug, "configuring input device")
|
r.cfg.Logger.Debug("configuring input device")
|
||||||
err := d.Setup(r.cfg)
|
err := d.Setup(r.cfg)
|
||||||
switch err := err.(type) {
|
switch err := err.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
case device.MultiError:
|
case device.MultiError:
|
||||||
r.cfg.Logger.Log(logger.Warning, "errors from configuring input device", "errors", err)
|
r.cfg.Logger.Warning("errors from configuring input device", "errors", err)
|
||||||
default:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "input device configured")
|
r.cfg.Logger.Info("input device configured")
|
||||||
|
|
||||||
// Set revid's lexer.
|
// Set revid's lexer.
|
||||||
l, err := codecutil.NewByteLexer(d.DataSize())
|
l, err := codecutil.NewByteLexer(d.DataSize())
|
||||||
|
|
|
@ -29,19 +29,9 @@ package config
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Logger interface {
|
|
||||||
SetLevel(int8)
|
|
||||||
Log(level int8, message string, params ...interface{})
|
|
||||||
Debug(msg string, params ...interface{})
|
|
||||||
Info(msg string, params ...interface{})
|
|
||||||
Warning(msg string, params ...interface{})
|
|
||||||
Error(msg string, params ...interface{})
|
|
||||||
Fatal(msg string, params ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enums to define inputs, outputs and codecs.
|
// Enums to define inputs, outputs and codecs.
|
||||||
const (
|
const (
|
||||||
// Indicates no option has been set.
|
// Indicates no option has been set.
|
||||||
|
@ -188,11 +178,11 @@ type Config struct {
|
||||||
|
|
||||||
// Logger holds an implementation of the Logger interface as defined in revid.go.
|
// Logger holds an implementation of the Logger interface as defined in revid.go.
|
||||||
// This must be set for revid to work correctly.
|
// This must be set for revid to work correctly.
|
||||||
Logger Logger
|
Logger logging.Logger
|
||||||
|
|
||||||
// LogLevel is the revid logging verbosity level.
|
// LogLevel is the revid logging verbosity level.
|
||||||
// Valid values are defined by enums from the logger package: logger.Debug,
|
// Valid values are defined by enums from the logger package: logging.Debug,
|
||||||
// logger.Info, logger.Warning logger.Error, logger.Fatal.
|
// logging.Info, logging.Warning logging.Error, logging.Fatal.
|
||||||
LogLevel int8
|
LogLevel int8
|
||||||
|
|
||||||
Loop bool // If true will restart reading of input after an io.EOF.
|
Loop bool // If true will restart reading of input after an io.EOF.
|
||||||
|
@ -302,7 +292,7 @@ func (c *Config) Update(vars map[string]string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) LogInvalidField(name string, def interface{}) {
|
func (c *Config) LogInvalidField(name string, def interface{}) {
|
||||||
c.Logger.Log(logger.Info, name+" bad or unset, defaulting", name, def)
|
c.Logger.Info( name+" bad or unset, defaulting", name, def)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringInSlice(want string, slice []string) bool {
|
func stringInSlice(want string, slice []string) bool {
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ func TestUpdate(t *testing.T) {
|
||||||
Input: InputRTSP,
|
Input: InputRTSP,
|
||||||
InputCodec: codecutil.MJPEG,
|
InputCodec: codecutil.MJPEG,
|
||||||
InputPath: "/inputpath",
|
InputPath: "/inputpath",
|
||||||
LogLevel: logger.Error,
|
LogLevel: logging.Error,
|
||||||
Loop: true,
|
Loop: true,
|
||||||
MinFPS: 30,
|
MinFPS: 30,
|
||||||
MinFrames: 30,
|
MinFrames: 30,
|
||||||
|
|
|
@ -34,7 +34,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config map Keys.
|
// Config map Keys.
|
||||||
|
@ -117,7 +117,7 @@ const (
|
||||||
defaultInput = InputRaspivid
|
defaultInput = InputRaspivid
|
||||||
defaultOutput = OutputHTTP
|
defaultOutput = OutputHTTP
|
||||||
defaultInputCodec = codecutil.H264
|
defaultInputCodec = codecutil.H264
|
||||||
defaultVerbosity = logger.Error
|
defaultVerbosity = logging.Error
|
||||||
defaultRTPAddr = "localhost:6970"
|
defaultRTPAddr = "localhost:6970"
|
||||||
defaultCameraIP = "192.168.1.50"
|
defaultCameraIP = "192.168.1.50"
|
||||||
defaultBurstPeriod = 10 // Seconds
|
defaultBurstPeriod = 10 // Seconds
|
||||||
|
@ -149,7 +149,7 @@ var Variables = []struct {
|
||||||
Name: KeyTransformMatrix,
|
Name: KeyTransformMatrix,
|
||||||
Type: typeString,
|
Type: typeString,
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
c.Logger.Log(logger.Debug, "updating transform matrix", "string", v)
|
c.Logger.Debug( "updating transform matrix", "string", v)
|
||||||
v = strings.Replace(v, " ", "", -1)
|
v = strings.Replace(v, " ", "", -1)
|
||||||
vals := make([]float64, 0)
|
vals := make([]float64, 0)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
|
@ -161,7 +161,7 @@ var Variables = []struct {
|
||||||
for _, e := range elements {
|
for _, e := range elements {
|
||||||
vFloat, err := strconv.ParseFloat(e, 64)
|
vFloat, err := strconv.ParseFloat(e, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid TransformMatrix param", "value", e)
|
c.Logger.Warning( "invalid TransformMatrix param", "value", e)
|
||||||
}
|
}
|
||||||
vals = append(vals, vFloat)
|
vals = append(vals, vFloat)
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
_v, err := strconv.Atoi(v)
|
_v, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid ClipDuration param", "value", v)
|
c.Logger.Warning( "invalid ClipDuration param", "value", v)
|
||||||
}
|
}
|
||||||
c.ClipDuration = time.Duration(_v) * time.Second
|
c.ClipDuration = time.Duration(_v) * time.Second
|
||||||
},
|
},
|
||||||
|
@ -283,7 +283,7 @@ var Variables = []struct {
|
||||||
for i, filter := range filters {
|
for i, filter := range filters {
|
||||||
v, ok := m[filter]
|
v, ok := m[filter]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.Logger.Log(logger.Warning, "invalid Filters param", "value", v)
|
c.Logger.Warning( "invalid Filters param", "value", v)
|
||||||
}
|
}
|
||||||
c.Filters[i] = uint(v)
|
c.Filters[i] = uint(v)
|
||||||
}
|
}
|
||||||
|
@ -371,22 +371,22 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
switch v {
|
switch v {
|
||||||
case "Debug":
|
case "Debug":
|
||||||
c.LogLevel = logger.Debug
|
c.LogLevel = logging.Debug
|
||||||
case "Info":
|
case "Info":
|
||||||
c.LogLevel = logger.Info
|
c.LogLevel = logging.Info
|
||||||
case "Warning":
|
case "Warning":
|
||||||
c.LogLevel = logger.Warning
|
c.LogLevel = logging.Warning
|
||||||
case "Error":
|
case "Error":
|
||||||
c.LogLevel = logger.Error
|
c.LogLevel = logging.Error
|
||||||
case "Fatal":
|
case "Fatal":
|
||||||
c.LogLevel = logger.Fatal
|
c.LogLevel = logging.Fatal
|
||||||
default:
|
default:
|
||||||
c.Logger.Log(logger.Warning, "invalid Logging param", "value", v)
|
c.Logger.Warning( "invalid Logging param", "value", v)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Validate: func(c *Config) {
|
Validate: func(c *Config) {
|
||||||
switch c.LogLevel {
|
switch c.LogLevel {
|
||||||
case logger.Debug, logger.Info, logger.Warning, logger.Error, logger.Fatal:
|
case logging.Debug, logging.Info, logging.Warning, logging.Error, logging.Fatal:
|
||||||
default:
|
default:
|
||||||
c.LogInvalidField("LogLevel", defaultVerbosity)
|
c.LogInvalidField("LogLevel", defaultVerbosity)
|
||||||
c.LogLevel = defaultVerbosity
|
c.LogLevel = defaultVerbosity
|
||||||
|
@ -452,7 +452,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
f, err := strconv.ParseFloat(v, 64)
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid MotionMinArea var", "value", v)
|
c.Logger.Warning( "invalid MotionMinArea var", "value", v)
|
||||||
}
|
}
|
||||||
c.MotionMinArea = f
|
c.MotionMinArea = f
|
||||||
},
|
},
|
||||||
|
@ -473,7 +473,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
f, err := strconv.ParseFloat(v, 64)
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid MotionThreshold var", "value", v)
|
c.Logger.Warning( "invalid MotionThreshold var", "value", v)
|
||||||
}
|
}
|
||||||
c.MotionThreshold = f
|
c.MotionThreshold = f
|
||||||
},
|
},
|
||||||
|
@ -495,7 +495,7 @@ var Variables = []struct {
|
||||||
case "rtp":
|
case "rtp":
|
||||||
c.Outputs[0] = OutputRTP
|
c.Outputs[0] = OutputRTP
|
||||||
default:
|
default:
|
||||||
c.Logger.Log(logger.Warning, "invalid output param", "value", v)
|
c.Logger.Warning( "invalid output param", "value", v)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -523,7 +523,7 @@ var Variables = []struct {
|
||||||
case "rtp":
|
case "rtp":
|
||||||
c.Outputs[i] = OutputRTP
|
c.Outputs[i] = OutputRTP
|
||||||
default:
|
default:
|
||||||
c.Logger.Log(logger.Warning, "invalid outputs param", "value", v)
|
c.Logger.Warning( "invalid outputs param", "value", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -575,7 +575,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
_v, err := strconv.ParseFloat(v, 64)
|
_v, err := strconv.ParseFloat(v, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, fmt.Sprintf("invalid %s param", KeyRecPeriod), "value", v)
|
c.Logger.Warning( fmt.Sprintf("invalid %s param", KeyRecPeriod), "value", v)
|
||||||
}
|
}
|
||||||
c.RecPeriod = _v
|
c.RecPeriod = _v
|
||||||
},
|
},
|
||||||
|
@ -622,7 +622,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
_v, err := strconv.Atoi(v)
|
_v, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid JPEGQuality param", "value", v)
|
c.Logger.Warning( "invalid JPEGQuality param", "value", v)
|
||||||
}
|
}
|
||||||
c.JPEGQuality = _v
|
c.JPEGQuality = _v
|
||||||
},
|
},
|
||||||
|
@ -632,7 +632,7 @@ var Variables = []struct {
|
||||||
Type: typeBool,
|
Type: typeBool,
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
c.Suppress = parseBool(KeySuppress, v, c)
|
c.Suppress = parseBool(KeySuppress, v, c)
|
||||||
c.Logger.(*logger.Logger).SetSuppress(c.Suppress)
|
c.Logger.(*logging.JSONLogger).SetSuppress(c.Suppress)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -641,7 +641,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
_v, err := strconv.Atoi(v)
|
_v, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid TimelapseInterval param", "value", v)
|
c.Logger.Warning( "invalid TimelapseInterval param", "value", v)
|
||||||
}
|
}
|
||||||
c.TimelapseInterval = time.Duration(_v) * time.Second
|
c.TimelapseInterval = time.Duration(_v) * time.Second
|
||||||
},
|
},
|
||||||
|
@ -652,7 +652,7 @@ var Variables = []struct {
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
_v, err := strconv.Atoi(v)
|
_v, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid TimelapseDuration param", "value", v)
|
c.Logger.Warning( "invalid TimelapseDuration param", "value", v)
|
||||||
}
|
}
|
||||||
c.TimelapseDuration = time.Duration(_v) * time.Second
|
c.TimelapseDuration = time.Duration(_v) * time.Second
|
||||||
},
|
},
|
||||||
|
@ -695,7 +695,7 @@ var Variables = []struct {
|
||||||
func parseUint(n, v string, c *Config) uint {
|
func parseUint(n, v string, c *Config) uint {
|
||||||
_v, err := strconv.ParseUint(v, 10, 64)
|
_v, err := strconv.ParseUint(v, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, fmt.Sprintf("expected unsigned int for param %s", n), "value", v)
|
c.Logger.Warning( fmt.Sprintf("expected unsigned int for param %s", n), "value", v)
|
||||||
}
|
}
|
||||||
return uint(_v)
|
return uint(_v)
|
||||||
}
|
}
|
||||||
|
@ -703,7 +703,7 @@ func parseUint(n, v string, c *Config) uint {
|
||||||
func parseInt(n, v string, c *Config) int {
|
func parseInt(n, v string, c *Config) int {
|
||||||
_v, err := strconv.Atoi(v)
|
_v, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, fmt.Sprintf("expected integer for param %s", n), "value", v)
|
c.Logger.Warning( fmt.Sprintf("expected integer for param %s", n), "value", v)
|
||||||
}
|
}
|
||||||
return _v
|
return _v
|
||||||
}
|
}
|
||||||
|
@ -715,7 +715,7 @@ func parseBool(n, v string, c *Config) (b bool) {
|
||||||
case "false":
|
case "false":
|
||||||
b = false
|
b = false
|
||||||
default:
|
default:
|
||||||
c.Logger.Log(logger.Warning, fmt.Sprintf("expect bool for param %s", n), "value", v)
|
c.Logger.Warning( fmt.Sprintf("expect bool for param %s", n), "value", v)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -723,7 +723,7 @@ func parseBool(n, v string, c *Config) (b bool) {
|
||||||
func parseEnum(n, v string, enums map[string]uint8, c *Config) uint8 {
|
func parseEnum(n, v string, enums map[string]uint8, c *Config) uint8 {
|
||||||
_v, ok := enums[strings.ToLower(v)]
|
_v, ok := enums[strings.ToLower(v)]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.Logger.Log(logger.Warning, fmt.Sprintf("invalid value for %s param", n), "value", v)
|
c.Logger.Warning( fmt.Sprintf("invalid value for %s param", n), "value", v)
|
||||||
}
|
}
|
||||||
return _v
|
return _v
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ import (
|
||||||
"bitbucket.org/ausocean/av/filter"
|
"bitbucket.org/ausocean/av/filter"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/utils/ioext"
|
"bitbucket.org/ausocean/utils/ioext"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
|
||||||
"bitbucket.org/ausocean/utils/pool"
|
"bitbucket.org/ausocean/utils/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ func (r *Revid) handleErrors() {
|
||||||
for {
|
for {
|
||||||
err := <-r.err
|
err := <-r.err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Error, "async error", "error", err.Error())
|
r.cfg.Logger.Error("async error", "error", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,14 +66,14 @@ func (r *Revid) handleErrors() {
|
||||||
// configuration; checking validity and returning errors if not valid. It then
|
// configuration; checking validity and returning errors if not valid. It then
|
||||||
// sets up the data pipeline accordingly to this configuration.
|
// sets up the data pipeline accordingly to this configuration.
|
||||||
func (r *Revid) reset(c config.Config) error {
|
func (r *Revid) reset(c config.Config) error {
|
||||||
r.cfg.Logger.Log(logger.Debug, "setting config")
|
r.cfg.Logger.Debug("setting config")
|
||||||
err := r.setConfig(c)
|
err := r.setConfig(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not set config: %w", err)
|
return fmt.Errorf("could not set config: %w", err)
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "config set")
|
r.cfg.Logger.Info("config set")
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "setting up revid pipeline")
|
r.cfg.Logger.Debug("setting up revid pipeline")
|
||||||
|
|
||||||
err = r.setupPipeline(
|
err = r.setupPipeline(
|
||||||
func(dst io.WriteCloser, rate float64) (io.WriteCloser, error) {
|
func(dst io.WriteCloser, rate float64) (io.WriteCloser, error) {
|
||||||
|
@ -130,7 +129,7 @@ func (r *Revid) reset(c config.Config) error {
|
||||||
},
|
},
|
||||||
ioext.MultiWriteCloser,
|
ioext.MultiWriteCloser,
|
||||||
)
|
)
|
||||||
r.cfg.Logger.Log(logger.Info, "finished setting pipeline")
|
r.cfg.Logger.Info("finished setting pipeline")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not set up pipeline: %w", err)
|
return fmt.Errorf("could not set up pipeline: %w", err)
|
||||||
|
@ -143,12 +142,12 @@ func (r *Revid) reset(c config.Config) error {
|
||||||
// revid config.
|
// revid config.
|
||||||
func (r *Revid) setConfig(config config.Config) error {
|
func (r *Revid) setConfig(config config.Config) error {
|
||||||
r.cfg.Logger = config.Logger
|
r.cfg.Logger = config.Logger
|
||||||
r.cfg.Logger.Log(logger.Debug, "validating config")
|
r.cfg.Logger.Debug("validating config")
|
||||||
err := config.Validate()
|
err := config.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Config struct is bad: " + err.Error())
|
return errors.New("Config struct is bad: " + err.Error())
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "config validated")
|
r.cfg.Logger.Info("config validated")
|
||||||
r.cfg = config
|
r.cfg = config
|
||||||
r.cfg.Logger.SetLevel(r.cfg.LogLevel)
|
r.cfg.Logger.SetLevel(r.cfg.LogLevel)
|
||||||
return nil
|
return nil
|
||||||
|
@ -182,28 +181,28 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
for _, out := range r.cfg.Outputs {
|
for _, out := range r.cfg.Outputs {
|
||||||
switch out {
|
switch out {
|
||||||
case config.OutputHTTP:
|
case config.OutputHTTP:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using HTTP output")
|
r.cfg.Logger.Debug("using HTTP output")
|
||||||
pb := pool.NewBuffer(int(r.cfg.PoolStartElementSize), int(nElements), writeTimeout)
|
pb := pool.NewBuffer(int(r.cfg.PoolStartElementSize), int(nElements), writeTimeout)
|
||||||
hs := newHTTPSender(r.ns, r.cfg.Logger.Log, r.bitrate.Report)
|
hs := newHTTPSender(r.ns, r.cfg.Logger.Log, r.bitrate.Report)
|
||||||
w = newMTSSender(hs, r.cfg.Logger.Log, pb, r.cfg.ClipDuration)
|
w = newMTSSender(hs, r.cfg.Logger.Log, pb, r.cfg.ClipDuration)
|
||||||
mtsSenders = append(mtsSenders, w)
|
mtsSenders = append(mtsSenders, w)
|
||||||
|
|
||||||
case config.OutputRTP:
|
case config.OutputRTP:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using RTP output")
|
r.cfg.Logger.Debug("using RTP output")
|
||||||
w, err := newRtpSender(r.cfg.RTPAddress, r.cfg.Logger.Log, r.cfg.FrameRate, r.bitrate.Report)
|
w, err := newRtpSender(r.cfg.RTPAddress, r.cfg.Logger.Log, r.cfg.FrameRate, r.bitrate.Report)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Warning, "rtp connect error", "error", err.Error())
|
r.cfg.Logger.Warning("rtp connect error", "error", err.Error())
|
||||||
}
|
}
|
||||||
mtsSenders = append(mtsSenders, w)
|
mtsSenders = append(mtsSenders, w)
|
||||||
case config.OutputFile:
|
case config.OutputFile:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using File output")
|
r.cfg.Logger.Debug("using File output")
|
||||||
w, err := newFileSender(r.cfg.Logger, r.cfg.OutputPath, false)
|
w, err := newFileSender(r.cfg.Logger, r.cfg.OutputPath, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mtsSenders = append(mtsSenders, w)
|
mtsSenders = append(mtsSenders, w)
|
||||||
case config.OutputFiles:
|
case config.OutputFiles:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using Files output")
|
r.cfg.Logger.Debug("using Files output")
|
||||||
pb := pool.NewBuffer(int(r.cfg.PoolStartElementSize), int(nElements), writeTimeout)
|
pb := pool.NewBuffer(int(r.cfg.PoolStartElementSize), int(nElements), writeTimeout)
|
||||||
fs, err := newFileSender(r.cfg.Logger, r.cfg.OutputPath, true)
|
fs, err := newFileSender(r.cfg.Logger, r.cfg.OutputPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -212,11 +211,11 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
w = newMTSSender(fs, r.cfg.Logger.Log, pb, r.cfg.ClipDuration)
|
w = newMTSSender(fs, r.cfg.Logger.Log, pb, r.cfg.ClipDuration)
|
||||||
mtsSenders = append(mtsSenders, w)
|
mtsSenders = append(mtsSenders, w)
|
||||||
case config.OutputRTMP:
|
case config.OutputRTMP:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using RTMP output")
|
r.cfg.Logger.Debug("using RTMP output")
|
||||||
pb := pool.NewBuffer(int(r.cfg.PoolStartElementSize), int(nElements), writeTimeout)
|
pb := pool.NewBuffer(int(r.cfg.PoolStartElementSize), int(nElements), writeTimeout)
|
||||||
w, err := newRtmpSender(r.cfg.RTMPURL, rtmpConnectionMaxTries, pb, r.cfg.Logger.Log, r.bitrate.Report)
|
w, err := newRtmpSender(r.cfg.RTMPURL, rtmpConnectionMaxTries, pb, r.cfg.Logger.Log, r.bitrate.Report)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Warning, "rtmp connect error", "error", err.Error())
|
r.cfg.Logger.Warning("rtmp connect error", "error", err.Error())
|
||||||
}
|
}
|
||||||
flvSenders = append(flvSenders, w)
|
flvSenders = append(flvSenders, w)
|
||||||
}
|
}
|
||||||
|
@ -251,68 +250,67 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
l := len(r.cfg.Filters)
|
l := len(r.cfg.Filters)
|
||||||
r.filters = []filter.Filter{filter.NewNoOp(r.encoders)}
|
r.filters = []filter.Filter{filter.NewNoOp(r.encoders)}
|
||||||
if l != 0 {
|
if l != 0 {
|
||||||
r.cfg.Logger.Log(logger.Debug, "setting up filters", "filters", r.cfg.Filters)
|
r.cfg.Logger.Debug("setting up filters", "filters", r.cfg.Filters)
|
||||||
r.filters = make([]filter.Filter, l)
|
r.filters = make([]filter.Filter, l)
|
||||||
dst := r.encoders
|
dst := r.encoders
|
||||||
|
|
||||||
for i := l - 1; i >= 0; i-- {
|
for i := l - 1; i >= 0; i-- {
|
||||||
switch r.cfg.Filters[i] {
|
switch r.cfg.Filters[i] {
|
||||||
case config.FilterNoOp:
|
case config.FilterNoOp:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using NoOp filter")
|
r.cfg.Logger.Debug("using NoOp filter")
|
||||||
r.filters[i] = filter.NewNoOp(dst)
|
r.filters[i] = filter.NewNoOp(dst)
|
||||||
case config.FilterMOG:
|
case config.FilterMOG:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using MOG filter")
|
r.cfg.Logger.Debug("using MOG filter")
|
||||||
r.filters[i] = filter.NewMOG(dst, r.cfg)
|
r.filters[i] = filter.NewMOG(dst, r.cfg)
|
||||||
case config.FilterVariableFPS:
|
case config.FilterVariableFPS:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using Variable FPS MOG filter")
|
r.cfg.Logger.Debug("using Variable FPS MOG filter")
|
||||||
r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg))
|
r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg))
|
||||||
case config.FilterKNN:
|
case config.FilterKNN:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using KNN filter")
|
r.cfg.Logger.Debug("using KNN filter")
|
||||||
r.filters[i] = filter.NewKNN(dst, r.cfg)
|
r.filters[i] = filter.NewKNN(dst, r.cfg)
|
||||||
case config.FilterDiff:
|
case config.FilterDiff:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using gocv difference filter")
|
r.cfg.Logger.Debug("using gocv difference filter")
|
||||||
r.filters[i] = filter.NewDiff(dst, r.cfg)
|
r.filters[i] = filter.NewDiff(dst, r.cfg)
|
||||||
case config.FilterBasic:
|
case config.FilterBasic:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using go difference filter")
|
r.cfg.Logger.Debug("using go difference filter")
|
||||||
r.filters[i] = filter.NewBasic(dst, r.cfg)
|
r.filters[i] = filter.NewBasic(dst, r.cfg)
|
||||||
default:
|
default:
|
||||||
panic("unknown filter")
|
panic("unknown filter")
|
||||||
}
|
}
|
||||||
dst = r.filters[i]
|
dst = r.filters[i]
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "filters set up")
|
r.cfg.Logger.Info("filters set up")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
switch r.cfg.Input {
|
switch r.cfg.Input {
|
||||||
case config.InputRaspivid:
|
case config.InputRaspivid:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using raspivid input")
|
r.cfg.Logger.Debug("using raspivid input")
|
||||||
r.input = raspivid.New(r.cfg.Logger)
|
r.input = raspivid.New(r.cfg.Logger)
|
||||||
err = r.setLexer(r.cfg.InputCodec, false)
|
err = r.setLexer(r.cfg.InputCodec, false)
|
||||||
|
|
||||||
case config.InputRaspistill:
|
case config.InputRaspistill:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using raspistill input")
|
r.cfg.Logger.Debug("using raspistill input")
|
||||||
r.input = raspistill.New(r.cfg.Logger)
|
r.input = raspistill.New(r.cfg.Logger)
|
||||||
r.setLexer(r.cfg.InputCodec, false)
|
r.setLexer(r.cfg.InputCodec, false)
|
||||||
|
|
||||||
case config.InputV4L:
|
case config.InputV4L:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using V4L input")
|
r.cfg.Logger.Debug("using V4L input")
|
||||||
r.input = webcam.New(r.cfg.Logger)
|
r.input = webcam.New(r.cfg.Logger)
|
||||||
err = r.setLexer(r.cfg.InputCodec, false)
|
err = r.setLexer(r.cfg.InputCodec, false)
|
||||||
|
|
||||||
case config.InputFile:
|
case config.InputFile:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using file input")
|
r.cfg.Logger.Debug("using file input")
|
||||||
r.input = file.New()
|
r.input = file.New()
|
||||||
err = r.setLexer(r.cfg.InputCodec, false)
|
err = r.setLexer(r.cfg.InputCodec, false)
|
||||||
|
|
||||||
case config.InputRTSP:
|
case config.InputRTSP:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using RTSP input")
|
r.cfg.Logger.Debug("using RTSP input")
|
||||||
r.input = geovision.New(r.cfg.Logger)
|
r.input = geovision.New(r.cfg.Logger)
|
||||||
err = r.setLexer(r.cfg.InputCodec, true)
|
err = r.setLexer(r.cfg.InputCodec, true)
|
||||||
|
|
||||||
case config.InputAudio:
|
case config.InputAudio:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using audio input")
|
r.cfg.Logger.Debug("using audio input")
|
||||||
err = r.setupAudio()
|
err = r.setupAudio()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -321,12 +319,12 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
|
|
||||||
// Configure the input device. We know that defaults are set, so no need to
|
// Configure the input device. We know that defaults are set, so no need to
|
||||||
// return error, but we should log.
|
// return error, but we should log.
|
||||||
r.cfg.Logger.Log(logger.Debug, "configuring input device")
|
r.cfg.Logger.Debug("configuring input device")
|
||||||
err = r.input.Set(r.cfg)
|
err = r.input.Set(r.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Warning, "errors from configuring input device", "errors", err)
|
r.cfg.Logger.Warning("errors from configuring input device", "errors", err)
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "input device configured")
|
r.cfg.Logger.Info("input device configured")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -336,19 +334,19 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
func (r *Revid) setLexer(c string, isRTSP bool) error {
|
func (r *Revid) setLexer(c string, isRTSP bool) error {
|
||||||
switch c {
|
switch c {
|
||||||
case codecutil.H264:
|
case codecutil.H264:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using H.264 codec")
|
r.cfg.Logger.Debug("using H.264 codec")
|
||||||
r.lexTo = h264.Lex
|
r.lexTo = h264.Lex
|
||||||
if isRTSP {
|
if isRTSP {
|
||||||
r.lexTo = h264.NewExtractor().Extract
|
r.lexTo = h264.NewExtractor().Extract
|
||||||
}
|
}
|
||||||
case codecutil.H265:
|
case codecutil.H265:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using H.265 codec")
|
r.cfg.Logger.Debug("using H.265 codec")
|
||||||
r.lexTo = h265.NewExtractor(false).Extract
|
r.lexTo = h265.NewExtractor(false).Extract
|
||||||
if !isRTSP {
|
if !isRTSP {
|
||||||
return errors.New("byte stream h.265 lexing not implemented")
|
return errors.New("byte stream h.265 lexing not implemented")
|
||||||
}
|
}
|
||||||
case codecutil.MJPEG, codecutil.JPEG:
|
case codecutil.MJPEG, codecutil.JPEG:
|
||||||
r.cfg.Logger.Log(logger.Debug, "using MJPEG/JPEG codec")
|
r.cfg.Logger.Debug("using MJPEG/JPEG codec")
|
||||||
r.lexTo = jpeg.Lex
|
r.lexTo = jpeg.Lex
|
||||||
jpeg.Log = r.cfg.Logger
|
jpeg.Log = r.cfg.Logger
|
||||||
if isRTSP {
|
if isRTSP {
|
||||||
|
@ -377,7 +375,7 @@ func (r *Revid) processFrom(in device.AVDevice, delay time.Duration) {
|
||||||
// Lex data from input device, in, until finished or an error is encountered.
|
// Lex data from input device, in, until finished or an error is encountered.
|
||||||
// For a continuous source e.g. a camera or microphone, we should remain
|
// For a continuous source e.g. a camera or microphone, we should remain
|
||||||
// in this call indefinitely unless in.Stop() is called and an io.EOF is forced.
|
// in this call indefinitely unless in.Stop() is called and an io.EOF is forced.
|
||||||
r.cfg.Logger.Log(logger.Debug, "lexing")
|
r.cfg.Logger.Debug("lexing")
|
||||||
var w io.Writer
|
var w io.Writer
|
||||||
w = r.filters[0]
|
w = r.filters[0]
|
||||||
if r.probe != nil {
|
if r.probe != nil {
|
||||||
|
@ -387,19 +385,19 @@ func (r *Revid) processFrom(in device.AVDevice, delay time.Duration) {
|
||||||
err = r.lexTo(w, in, delay)
|
err = r.lexTo(w, in, delay)
|
||||||
switch err {
|
switch err {
|
||||||
case nil, io.EOF:
|
case nil, io.EOF:
|
||||||
r.cfg.Logger.Log(logger.Info, "end of file")
|
r.cfg.Logger.Info("end of file")
|
||||||
case io.ErrUnexpectedEOF:
|
case io.ErrUnexpectedEOF:
|
||||||
r.cfg.Logger.Log(logger.Info, "unexpected EOF from input")
|
r.cfg.Logger.Info("unexpected EOF from input")
|
||||||
default:
|
default:
|
||||||
r.err <- err
|
r.err <- err
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "finished reading input")
|
r.cfg.Logger.Info("finished reading input")
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "stopping input")
|
r.cfg.Logger.Debug("stopping input")
|
||||||
err = in.Stop()
|
err = in.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.err <- fmt.Errorf("could not stop input source: %w", err)
|
r.err <- fmt.Errorf("could not stop input source: %w", err)
|
||||||
} else {
|
} else {
|
||||||
r.cfg.Logger.Log(logger.Info, "input stopped")
|
r.cfg.Logger.Info("input stopped")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ import (
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/utils/bitrate"
|
"bitbucket.org/ausocean/utils/bitrate"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Misc consts.
|
// Misc consts.
|
||||||
|
@ -131,19 +130,19 @@ func (r *Revid) Bitrate() int {
|
||||||
// and packetising (if theres packetization) to a defined output.
|
// and packetising (if theres packetization) to a defined output.
|
||||||
func (r *Revid) Start() error {
|
func (r *Revid) Start() error {
|
||||||
if r.running {
|
if r.running {
|
||||||
r.cfg.Logger.Log(logger.Warning, "start called, but revid already running")
|
r.cfg.Logger.Warning("start called, but revid already running")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r.stop = make(chan struct{})
|
r.stop = make(chan struct{})
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "resetting revid")
|
r.cfg.Logger.Debug("resetting revid")
|
||||||
err := r.reset(r.cfg)
|
err := r.reset(r.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Stop()
|
r.Stop()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "revid reset")
|
r.cfg.Logger.Info("revid reset")
|
||||||
|
|
||||||
// Calculate delay between frames based on FileFPS for video or
|
// Calculate delay between frames based on FileFPS for video or
|
||||||
// between recording periods for audio.
|
// between recording periods for audio.
|
||||||
|
@ -154,7 +153,7 @@ func (r *Revid) Start() error {
|
||||||
d = time.Duration(1000/r.cfg.FileFPS) * time.Millisecond
|
d = time.Duration(1000/r.cfg.FileFPS) * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "starting input processing routine")
|
r.cfg.Logger.Debug("starting input processing routine")
|
||||||
r.wg.Add(1)
|
r.wg.Add(1)
|
||||||
go r.processFrom(r.input, d)
|
go r.processFrom(r.input, d)
|
||||||
|
|
||||||
|
@ -166,59 +165,59 @@ func (r *Revid) Start() error {
|
||||||
// connections, and/or files.
|
// connections, and/or files.
|
||||||
func (r *Revid) Stop() {
|
func (r *Revid) Stop() {
|
||||||
if !r.running {
|
if !r.running {
|
||||||
r.cfg.Logger.Log(logger.Warning, "stop called but revid isn't running")
|
r.cfg.Logger.Warning("stop called but revid isn't running")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
close(r.stop)
|
close(r.stop)
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "stopping input")
|
r.cfg.Logger.Debug("stopping input")
|
||||||
err := r.input.Stop()
|
err := r.input.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Error, "could not stop input", "error", err.Error())
|
r.cfg.Logger.Error("could not stop input", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
r.cfg.Logger.Log(logger.Info, "input stopped")
|
r.cfg.Logger.Info("input stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "closing pipeline")
|
r.cfg.Logger.Debug("closing pipeline")
|
||||||
err = r.encoders.Close()
|
err = r.encoders.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Error, "failed to close pipeline", "error", err.Error())
|
r.cfg.Logger.Error("failed to close pipeline", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
r.cfg.Logger.Log(logger.Info, "pipeline closed")
|
r.cfg.Logger.Info("pipeline closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, filter := range r.filters {
|
for _, filter := range r.filters {
|
||||||
err = filter.Close()
|
err = filter.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Error, "failed to close filters", "error", err.Error())
|
r.cfg.Logger.Error("failed to close filters", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
r.cfg.Logger.Log(logger.Info, "filters closed")
|
r.cfg.Logger.Info("filters closed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "waiting for routines to finish")
|
r.cfg.Logger.Debug("waiting for routines to finish")
|
||||||
r.wg.Wait()
|
r.wg.Wait()
|
||||||
r.cfg.Logger.Log(logger.Info, "routines finished")
|
r.cfg.Logger.Info("routines finished")
|
||||||
|
|
||||||
r.running = false
|
r.running = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Burst starts revid, waits for time specified, and then stops revid.
|
// Burst starts revid, waits for time specified, and then stops revid.
|
||||||
func (r *Revid) Burst() error {
|
func (r *Revid) Burst() error {
|
||||||
r.cfg.Logger.Log(logger.Debug, "starting revid")
|
r.cfg.Logger.Debug("starting revid")
|
||||||
err := r.Start()
|
err := r.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not start revid: %w", err)
|
return fmt.Errorf("could not start revid: %w", err)
|
||||||
}
|
}
|
||||||
r.cfg.Logger.Log(logger.Info, "revid started")
|
r.cfg.Logger.Info("revid started")
|
||||||
|
|
||||||
dur := time.Duration(r.cfg.BurstPeriod) * time.Second
|
dur := time.Duration(r.cfg.BurstPeriod) * time.Second
|
||||||
time.Sleep(dur)
|
time.Sleep(dur)
|
||||||
|
|
||||||
r.cfg.Logger.Log(logger.Debug, "stopping revid")
|
r.cfg.Logger.Debug("stopping revid")
|
||||||
r.Stop()
|
r.Stop()
|
||||||
r.cfg.Logger.Log(logger.Info, "revid stopped")
|
r.cfg.Logger.Info("revid stopped")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -231,16 +230,16 @@ func (r *Revid) Running() bool {
|
||||||
// if the variables are recognised as valid parameters.
|
// if the variables are recognised as valid parameters.
|
||||||
func (r *Revid) Update(vars map[string]string) error {
|
func (r *Revid) Update(vars map[string]string) error {
|
||||||
if r.running {
|
if r.running {
|
||||||
r.cfg.Logger.Log(logger.Debug, "revid running; stopping for re-config")
|
r.cfg.Logger.Debug("revid running; stopping for re-config")
|
||||||
r.Stop()
|
r.Stop()
|
||||||
r.cfg.Logger.Log(logger.Info, "revid was running; stopped for re-config")
|
r.cfg.Logger.Info("revid was running; stopped for re-config")
|
||||||
}
|
}
|
||||||
|
|
||||||
//look through the vars and update revid where needed
|
//look through the vars and update revid where needed
|
||||||
r.cfg.Logger.Log(logger.Debug, "checking vars from server", "vars", vars)
|
r.cfg.Logger.Debug("checking vars from server", "vars", vars)
|
||||||
r.cfg.Update(vars)
|
r.cfg.Update(vars)
|
||||||
r.cfg.Logger.Log(logger.Info, "finished reconfig")
|
r.cfg.Logger.Info("finished reconfig")
|
||||||
r.cfg.Logger.Log(logger.Debug, "config changed", "config", r.cfg)
|
r.cfg.Logger.Debug("config changed", "config", r.cfg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,8 @@ import (
|
||||||
"bitbucket.org/ausocean/av/container/mts"
|
"bitbucket.org/ausocean/av/container/mts"
|
||||||
"bitbucket.org/ausocean/av/protocol/rtmp"
|
"bitbucket.org/ausocean/av/protocol/rtmp"
|
||||||
"bitbucket.org/ausocean/av/protocol/rtp"
|
"bitbucket.org/ausocean/av/protocol/rtp"
|
||||||
"bitbucket.org/ausocean/av/revid/config"
|
|
||||||
"bitbucket.org/ausocean/iot/pi/netsender"
|
"bitbucket.org/ausocean/iot/pi/netsender"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"bitbucket.org/ausocean/utils/pool"
|
"bitbucket.org/ausocean/utils/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,13 +81,13 @@ func newHTTPSender(ns *netsender.Sender, log func(lvl int8, msg string, args ...
|
||||||
|
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (s *httpSender) Write(d []byte) (int, error) {
|
func (s *httpSender) Write(d []byte) (int, error) {
|
||||||
s.log(logger.Debug, "HTTP sending")
|
s.log(logging.Debug, "HTTP sending")
|
||||||
err := httpSend(d, s.client, s.log)
|
err := httpSend(d, s.client, s.log)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.log(logger.Debug, "good send", "len", len(d))
|
s.log(logging.Debug, "good send", "len", len(d))
|
||||||
s.report(len(d))
|
s.report(len(d))
|
||||||
} else {
|
} else {
|
||||||
s.log(logger.Debug, "bad send", "error", err)
|
s.log(logging.Debug, "bad send", "error", err)
|
||||||
}
|
}
|
||||||
return len(d), err
|
return len(d), err
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,7 @@ func httpSend(d []byte, client *netsender.Sender, log func(lvl int8, msg string,
|
||||||
// Only send if "V0" or "S0" are configured as input.
|
// Only send if "V0" or "S0" are configured as input.
|
||||||
send := false
|
send := false
|
||||||
ip := client.Param("ip")
|
ip := client.Param("ip")
|
||||||
log(logger.Debug, "making pins, and sending recv request", "ip", ip)
|
log(logging.Debug, "making pins, and sending recv request", "ip", ip)
|
||||||
pins := netsender.MakePins(ip, "V,S")
|
pins := netsender.MakePins(ip, "V,S")
|
||||||
for i, pin := range pins {
|
for i, pin := range pins {
|
||||||
switch pin.Name {
|
switch pin.Name {
|
||||||
|
@ -125,7 +124,7 @@ func httpSend(d []byte, client *netsender.Sender, log func(lvl int8, msg string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log(logger.Debug, "good request", "reply", reply)
|
log(logging.Debug, "good request", "reply", reply)
|
||||||
return extractMeta(reply, log)
|
return extractMeta(reply, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +139,9 @@ func extractMeta(r string, log func(lvl int8, msg string, args ...interface{}))
|
||||||
if !mts.RealTime.IsSet() {
|
if !mts.RealTime.IsSet() {
|
||||||
t, err := dec.Int("ts")
|
t, err := dec.Int("ts")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(logger.Warning, "No timestamp in reply")
|
log(logging.Warning, "No timestamp in reply")
|
||||||
} else {
|
} else {
|
||||||
log(logger.Debug, "got timestamp", "ts", t)
|
log(logging.Debug, "got timestamp", "ts", t)
|
||||||
mts.RealTime.Set(time.Unix(int64(t), 0))
|
mts.RealTime.Set(time.Unix(int64(t), 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,9 +149,9 @@ func extractMeta(r string, log func(lvl int8, msg string, args ...interface{}))
|
||||||
// Extract location from reply
|
// Extract location from reply
|
||||||
g, err := dec.String("ll")
|
g, err := dec.String("ll")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(logger.Debug, "No location in reply")
|
log(logging.Debug, "No location in reply")
|
||||||
} else {
|
} else {
|
||||||
log(logger.Debug, fmt.Sprintf("got location: %v", g))
|
log(logging.Debug, fmt.Sprintf("got location: %v", g))
|
||||||
mts.Meta.Add(mts.LocationKey, g)
|
mts.Meta.Add(mts.LocationKey, g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,12 +165,12 @@ type fileSender struct {
|
||||||
multiFile bool
|
multiFile bool
|
||||||
path string
|
path string
|
||||||
init bool
|
init bool
|
||||||
log config.Logger
|
log logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFileSender returns a new fileSender. Setting multi true will write a new
|
// newFileSender returns a new fileSender. Setting multi true will write a new
|
||||||
// file for each write to this sender.
|
// file for each write to this sender.
|
||||||
func newFileSender(l config.Logger, path string, multiFile bool) (*fileSender, error) {
|
func newFileSender(l logging.Logger, path string, multiFile bool) (*fileSender, error) {
|
||||||
return &fileSender{
|
return &fileSender{
|
||||||
path: path,
|
path: path,
|
||||||
log: l,
|
log: l,
|
||||||
|
@ -219,7 +218,7 @@ type mtsSender struct {
|
||||||
|
|
||||||
// newMtsSender returns a new mtsSender.
|
// newMtsSender returns a new mtsSender.
|
||||||
func newMTSSender(dst io.WriteCloser, log func(lvl int8, msg string, args ...interface{}), rb *pool.Buffer, clipDur time.Duration) *mtsSender {
|
func newMTSSender(dst io.WriteCloser, log func(lvl int8, msg string, args ...interface{}), rb *pool.Buffer, clipDur time.Duration) *mtsSender {
|
||||||
log(logger.Debug, "setting up mtsSender", "clip duration", int(clipDur))
|
log(logging.Debug, "setting up mtsSender", "clip duration", int(clipDur))
|
||||||
s := &mtsSender{
|
s := &mtsSender{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
repairer: mts.NewDiscontinuityRepairer(),
|
repairer: mts.NewDiscontinuityRepairer(),
|
||||||
|
@ -239,7 +238,7 @@ func (s *mtsSender) output() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.done:
|
case <-s.done:
|
||||||
s.log(logger.Info, "terminating sender output routine")
|
s.log(logging.Info, "terminating sender output routine")
|
||||||
defer s.wg.Done()
|
defer s.wg.Done()
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
@ -251,10 +250,10 @@ func (s *mtsSender) output() {
|
||||||
case nil, io.EOF:
|
case nil, io.EOF:
|
||||||
continue
|
continue
|
||||||
case pool.ErrTimeout:
|
case pool.ErrTimeout:
|
||||||
s.log(logger.Debug, "mtsSender: pool buffer read timeout")
|
s.log(logging.Debug, "mtsSender: pool buffer read timeout")
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
s.log(logger.Error, "unexpected error", "error", err.Error())
|
s.log(logging.Error, "unexpected error", "error", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,14 +263,14 @@ func (s *mtsSender) output() {
|
||||||
chunk = nil
|
chunk = nil
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.log(logger.Debug, "mtsSender: writing")
|
s.log(logging.Debug, "mtsSender: writing")
|
||||||
_, err = s.dst.Write(chunk.Bytes())
|
_, err = s.dst.Write(chunk.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(logger.Debug, "failed write, repairing MTS", "error", err)
|
s.log(logging.Debug, "failed write, repairing MTS", "error", err)
|
||||||
s.repairer.Failed()
|
s.repairer.Failed()
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
s.log(logger.Debug, "good write")
|
s.log(logging.Debug, "good write")
|
||||||
}
|
}
|
||||||
chunk.Close()
|
chunk.Close()
|
||||||
chunk = nil
|
chunk = nil
|
||||||
|
@ -286,7 +285,7 @@ func (s *mtsSender) Write(d []byte) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.next != nil {
|
if s.next != nil {
|
||||||
s.log(logger.Debug, "appending packet to clip")
|
s.log(logging.Debug, "appending packet to clip")
|
||||||
s.buf = append(s.buf, s.next...)
|
s.buf = append(s.buf, s.next...)
|
||||||
}
|
}
|
||||||
bytes := make([]byte, len(d))
|
bytes := make([]byte, len(d))
|
||||||
|
@ -295,21 +294,21 @@ func (s *mtsSender) Write(d []byte) (int, error) {
|
||||||
p, _ := mts.PID(bytes)
|
p, _ := mts.PID(bytes)
|
||||||
s.curPid = int(p)
|
s.curPid = int(p)
|
||||||
curDur := time.Now().Sub(s.prev)
|
curDur := time.Now().Sub(s.prev)
|
||||||
s.log(logger.Debug, "checking send conditions", "curDuration", int(curDur), "sendDur", int(s.clipDur), "curPID", s.curPid, "len", len(s.buf))
|
s.log(logging.Debug, "checking send conditions", "curDuration", int(curDur), "sendDur", int(s.clipDur), "curPID", s.curPid, "len", len(s.buf))
|
||||||
if curDur >= s.clipDur && s.curPid == mts.PatPid && len(s.buf) > 0 {
|
if curDur >= s.clipDur && s.curPid == mts.PatPid && len(s.buf) > 0 {
|
||||||
s.log(logger.Debug, "writing clip to pool buffer for sending", "size", len(s.buf))
|
s.log(logging.Debug, "writing clip to pool buffer for sending", "size", len(s.buf))
|
||||||
s.prev = time.Now()
|
s.prev = time.Now()
|
||||||
n, err := s.pool.Write(s.buf)
|
n, err := s.pool.Write(s.buf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.pool.Flush()
|
s.pool.Flush()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(logger.Warning, "ringBuffer write error", "error", err.Error(), "n", n, "size", len(s.buf), "rb element size", adjustedMTSPoolElementSize)
|
s.log(logging.Warning, "ringBuffer write error", "error", err.Error(), "n", n, "size", len(s.buf), "rb element size", adjustedMTSPoolElementSize)
|
||||||
if err == pool.ErrTooLong {
|
if err == pool.ErrTooLong {
|
||||||
adjustedMTSPoolElementSize = len(s.buf) * 2
|
adjustedMTSPoolElementSize = len(s.buf) * 2
|
||||||
numElements := maxBuffLen / adjustedMTSPoolElementSize
|
numElements := maxBuffLen / adjustedMTSPoolElementSize
|
||||||
s.pool = pool.NewBuffer(maxBuffLen/adjustedMTSPoolElementSize, adjustedMTSPoolElementSize, 5*time.Second)
|
s.pool = pool.NewBuffer(maxBuffLen/adjustedMTSPoolElementSize, adjustedMTSPoolElementSize, 5*time.Second)
|
||||||
s.log(logger.Info, "adjusted MTS pool buffer element size", "new size", adjustedMTSPoolElementSize, "num elements", numElements, "size(MB)", numElements*adjustedMTSPoolElementSize)
|
s.log(logging.Info, "adjusted MTS pool buffer element size", "new size", adjustedMTSPoolElementSize, "num elements", numElements, "size(MB)", numElements*adjustedMTSPoolElementSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.buf = s.buf[:0]
|
s.buf = s.buf[:0]
|
||||||
|
@ -319,10 +318,10 @@ func (s *mtsSender) Write(d []byte) (int, error) {
|
||||||
|
|
||||||
// Close implements io.Closer.
|
// Close implements io.Closer.
|
||||||
func (s *mtsSender) Close() error {
|
func (s *mtsSender) Close() error {
|
||||||
s.log(logger.Debug, "closing sender output routine")
|
s.log(logging.Debug, "closing sender output routine")
|
||||||
close(s.done)
|
close(s.done)
|
||||||
s.wg.Wait()
|
s.wg.Wait()
|
||||||
s.log(logger.Info, "sender output routine closed")
|
s.log(logging.Info, "sender output routine closed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,9 +345,9 @@ func newRtmpSender(url string, retries int, rb *pool.Buffer, log func(lvl int8,
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
log(logger.Error, "dial error", "error", err)
|
log(logging.Error, "dial error", "error", err)
|
||||||
if n < retries-1 {
|
if n < retries-1 {
|
||||||
log(logger.Info, "retrying dial")
|
log(logging.Info, "retrying dial")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s := &rtmpSender{
|
s := &rtmpSender{
|
||||||
|
@ -371,7 +370,7 @@ func (s *rtmpSender) output() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.done:
|
case <-s.done:
|
||||||
s.log(logger.Info, "terminating sender output routine")
|
s.log(logging.Info, "terminating sender output routine")
|
||||||
defer s.wg.Done()
|
defer s.wg.Done()
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
@ -383,30 +382,30 @@ func (s *rtmpSender) output() {
|
||||||
case nil, io.EOF:
|
case nil, io.EOF:
|
||||||
continue
|
continue
|
||||||
case pool.ErrTimeout:
|
case pool.ErrTimeout:
|
||||||
s.log(logger.Debug, "rtmpSender: pool buffer read timeout")
|
s.log(logging.Debug, "rtmpSender: pool buffer read timeout")
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
s.log(logger.Error, "unexpected error", "error", err.Error())
|
s.log(logging.Error, "unexpected error", "error", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.conn == nil {
|
if s.conn == nil {
|
||||||
s.log(logger.Warning, "no rtmp connection, re-dialing")
|
s.log(logging.Warning, "no rtmp connection, re-dialing")
|
||||||
err := s.restart()
|
err := s.restart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(logger.Warning, "could not restart connection", "error", err)
|
s.log(logging.Warning, "could not restart connection", "error", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := s.conn.Write(chunk.Bytes())
|
_, err := s.conn.Write(chunk.Bytes())
|
||||||
switch err {
|
switch err {
|
||||||
case nil, rtmp.ErrInvalidFlvTag:
|
case nil, rtmp.ErrInvalidFlvTag:
|
||||||
s.log(logger.Debug, "good write to conn")
|
s.log(logging.Debug, "good write to conn")
|
||||||
default:
|
default:
|
||||||
s.log(logger.Warning, "send error, re-dialing", "error", err)
|
s.log(logging.Warning, "send error, re-dialing", "error", err)
|
||||||
err = s.restart()
|
err = s.restart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(logger.Warning, "could not restart connection", "error", err)
|
s.log(logging.Warning, "could not restart connection", "error", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -418,18 +417,18 @@ func (s *rtmpSender) output() {
|
||||||
|
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (s *rtmpSender) Write(d []byte) (int, error) {
|
func (s *rtmpSender) Write(d []byte) (int, error) {
|
||||||
s.log(logger.Debug, "writing to pool buffer")
|
s.log(logging.Debug, "writing to pool buffer")
|
||||||
_, err := s.pool.Write(d)
|
_, err := s.pool.Write(d)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.pool.Flush()
|
s.pool.Flush()
|
||||||
s.log(logger.Debug, "good pool buffer write", "len", len(d))
|
s.log(logging.Debug, "good pool buffer write", "len", len(d))
|
||||||
} else {
|
} else {
|
||||||
s.log(logger.Warning, "pool buffer write error", "error", err.Error())
|
s.log(logging.Warning, "pool buffer write error", "error", err.Error())
|
||||||
if err == pool.ErrTooLong {
|
if err == pool.ErrTooLong {
|
||||||
adjustedRTMPPoolElementSize = len(d) * 2
|
adjustedRTMPPoolElementSize = len(d) * 2
|
||||||
numElements := maxBuffLen / adjustedRTMPPoolElementSize
|
numElements := maxBuffLen / adjustedRTMPPoolElementSize
|
||||||
s.pool = pool.NewBuffer(numElements, adjustedRTMPPoolElementSize, 5*time.Second)
|
s.pool = pool.NewBuffer(numElements, adjustedRTMPPoolElementSize, 5*time.Second)
|
||||||
s.log(logger.Info, "adjusted RTMP pool buffer element size", "new size", adjustedRTMPPoolElementSize, "num elements", numElements, "size(MB)", numElements*adjustedRTMPPoolElementSize)
|
s.log(logging.Info, "adjusted RTMP pool buffer element size", "new size", adjustedRTMPPoolElementSize, "num elements", numElements, "size(MB)", numElements*adjustedRTMPPoolElementSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.report(len(d))
|
s.report(len(d))
|
||||||
|
@ -440,31 +439,31 @@ func (s *rtmpSender) restart() error {
|
||||||
s.close()
|
s.close()
|
||||||
var err error
|
var err error
|
||||||
for n := 0; n < s.retries; n++ {
|
for n := 0; n < s.retries; n++ {
|
||||||
s.log(logger.Debug, "dialing", "dials", n)
|
s.log(logging.Debug, "dialing", "dials", n)
|
||||||
s.conn, err = rtmp.Dial(s.url, s.log)
|
s.conn, err = rtmp.Dial(s.url, s.log)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s.log(logger.Error, "dial error", "error", err)
|
s.log(logging.Error, "dial error", "error", err)
|
||||||
if n < s.retries-1 {
|
if n < s.retries-1 {
|
||||||
s.log(logger.Info, "retry rtmp connection")
|
s.log(logging.Info, "retry rtmp connection")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rtmpSender) Close() error {
|
func (s *rtmpSender) Close() error {
|
||||||
s.log(logger.Debug, "closing output routine")
|
s.log(logging.Debug, "closing output routine")
|
||||||
if s.done != nil {
|
if s.done != nil {
|
||||||
close(s.done)
|
close(s.done)
|
||||||
}
|
}
|
||||||
s.wg.Wait()
|
s.wg.Wait()
|
||||||
s.log(logger.Info, "output routine closed")
|
s.log(logging.Info, "output routine closed")
|
||||||
return s.close()
|
return s.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rtmpSender) close() error {
|
func (s *rtmpSender) close() error {
|
||||||
s.log(logger.Debug, "closing connection")
|
s.log(logging.Debug, "closing connection")
|
||||||
if s.conn == nil {
|
if s.conn == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -499,7 +498,7 @@ func (s *rtpSender) Write(d []byte) (int, error) {
|
||||||
copy(s.data, d)
|
copy(s.data, d)
|
||||||
_, err := s.encoder.Write(s.data)
|
_, err := s.encoder.Write(s.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(logger.Warning, "rtpSender: write error", err.Error())
|
s.log(logging.Warning, "rtpSender: write error", err.Error())
|
||||||
}
|
}
|
||||||
s.report(len(d))
|
s.report(len(d))
|
||||||
return len(d), nil
|
return len(d), nil
|
||||||
|
|
|
@ -3,30 +3,30 @@ package revid
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testLogger will allow logging to be done by the testing pkg.
|
// testLogger will allow logging to be done by the testing pkg.
|
||||||
type testLogger testing.T
|
type testLogger testing.T
|
||||||
|
|
||||||
func (tl *testLogger) Debug(msg string, args ...interface{}) { tl.Log(logger.Debug, msg, args...) }
|
func (tl *testLogger) Debug(msg string, args ...interface{}) { tl.Log(logging.Debug, msg, args...) }
|
||||||
func (tl *testLogger) Info(msg string, args ...interface{}) { tl.Log(logger.Info, msg, args...) }
|
func (tl *testLogger) Info(msg string, args ...interface{}) { tl.Log(logging.Info, msg, args...) }
|
||||||
func (tl *testLogger) Warning(msg string, args ...interface{}) { tl.Log(logger.Warning, msg, args...) }
|
func (tl *testLogger) Warning(msg string, args ...interface{}) { tl.Log(logging.Warning, msg, args...) }
|
||||||
func (tl *testLogger) Error(msg string, args ...interface{}) { tl.Log(logger.Error, msg, args...) }
|
func (tl *testLogger) Error(msg string, args ...interface{}) { tl.Log(logging.Error, msg, args...) }
|
||||||
func (tl *testLogger) Fatal(msg string, args ...interface{}) { tl.Log(logger.Fatal, msg, args...) }
|
func (tl *testLogger) Fatal(msg string, args ...interface{}) { tl.Log(logging.Fatal, msg, args...) }
|
||||||
func (tl *testLogger) SetLevel(lvl int8) {}
|
func (tl *testLogger) SetLevel(lvl int8) {}
|
||||||
func (dl *testLogger) Log(lvl int8, msg string, args ...interface{}) {
|
func (dl *testLogger) Log(lvl int8, msg string, args ...interface{}) {
|
||||||
var l string
|
var l string
|
||||||
switch lvl {
|
switch lvl {
|
||||||
case logger.Warning:
|
case logging.Warning:
|
||||||
l = "warning"
|
l = "warning"
|
||||||
case logger.Debug:
|
case logging.Debug:
|
||||||
l = "debug"
|
l = "debug"
|
||||||
case logger.Info:
|
case logging.Info:
|
||||||
l = "info"
|
l = "info"
|
||||||
case logger.Error:
|
case logging.Error:
|
||||||
l = "error"
|
l = "error"
|
||||||
case logger.Fatal:
|
case logging.Fatal:
|
||||||
l = "fatal"
|
l = "fatal"
|
||||||
}
|
}
|
||||||
msg = l + ": " + msg
|
msg = l + ": " + msg
|
||||||
|
@ -44,7 +44,7 @@ func (dl *testLogger) Log(lvl int8, msg string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
msg += " )"
|
msg += " )"
|
||||||
|
|
||||||
if lvl == logger.Fatal {
|
if lvl == logging.Fatal {
|
||||||
dl.Fatalf(msg+"\n", args...)
|
dl.Fatalf(msg+"\n", args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"gocv.io/x/gocv"
|
"gocv.io/x/gocv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,11 +48,11 @@ type TurbiditySensor struct {
|
||||||
TransformMatrix gocv.Mat // The current perspective transformation matrix to extract the target from the frame.
|
TransformMatrix gocv.Mat // The current perspective transformation matrix to extract the target from the frame.
|
||||||
k1, k2, sobelFilterSize int
|
k1, k2, sobelFilterSize int
|
||||||
scale, alpha float64
|
scale, alpha float64
|
||||||
log logger.Logger
|
log logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTurbiditySensor returns a new TurbiditySensor.
|
// NewTurbiditySensor returns a new TurbiditySensor.
|
||||||
func NewTurbiditySensor(template, transformMatrix gocv.Mat, k1, k2, sobelFilterSize int, scale, alpha float64, log logger.Logger) (*TurbiditySensor, error) {
|
func NewTurbiditySensor(template, transformMatrix gocv.Mat, k1, k2, sobelFilterSize int, scale, alpha float64, log logging.Logger) (*TurbiditySensor, error) {
|
||||||
ts := new(TurbiditySensor)
|
ts := new(TurbiditySensor)
|
||||||
|
|
||||||
// Validate template image is not empty and has valid corners.
|
// Validate template image is not empty and has valid corners.
|
||||||
|
@ -82,18 +82,18 @@ func (ts TurbiditySensor) Evaluate(imgs []gocv.Mat) (*Results, error) {
|
||||||
return nil, fmt.Errorf("could not transform image: %d: %w", i, err)
|
return nil, fmt.Errorf("could not transform image: %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ts.log.Log(logger.Debug, "transform successful", "transform duration (sec)", time.Since(timer).Seconds())
|
ts.log.Debug( "transform successful", "transform duration (sec)", time.Since(timer).Seconds())
|
||||||
|
|
||||||
timer = time.Now()
|
timer = time.Now()
|
||||||
edge := ts.sobel(marker)
|
edge := ts.sobel(marker)
|
||||||
ts.log.Log(logger.Debug, "sobel filter successful", "sobel duration", time.Since(timer).Seconds())
|
ts.log.Debug( "sobel filter successful", "sobel duration", time.Since(timer).Seconds())
|
||||||
|
|
||||||
timer = time.Now()
|
timer = time.Now()
|
||||||
sharpScore, contScore, err := ts.EvaluateImage(marker, edge)
|
sharpScore, contScore, err := ts.EvaluateImage(marker, edge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
ts.log.Log(logger.Debug, "sharpness and contrast evaluation successful", "evaluation duration", time.Since(timer).Seconds())
|
ts.log.Debug( "sharpness and contrast evaluation successful", "evaluation duration", time.Since(timer).Seconds())
|
||||||
result.Update(sharpScore, contScore, float64(i), i)
|
result.Update(sharpScore, contScore, float64(i), i)
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
|
@ -33,7 +33,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logging"
|
||||||
"gocv.io/x/gocv"
|
"gocv.io/x/gocv"
|
||||||
"gonum.org/v1/gonum/stat"
|
"gonum.org/v1/gonum/stat"
|
||||||
"gonum.org/v1/plot"
|
"gonum.org/v1/plot"
|
||||||
|
@ -53,7 +53,7 @@ const (
|
||||||
logMaxSize = 500 // MB
|
logMaxSize = 500 // MB
|
||||||
logMaxBackup = 10
|
logMaxBackup = 10
|
||||||
logMaxAge = 28 // days
|
logMaxAge = 28 // days
|
||||||
logVerbosity = logger.Info
|
logVerbosity = logging.Info
|
||||||
logSuppress = true
|
logSuppress = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func TestImages(t *testing.T) {
|
||||||
MaxBackups: logMaxBackup,
|
MaxBackups: logMaxBackup,
|
||||||
MaxAge: logMaxAge,
|
MaxAge: logMaxAge,
|
||||||
}
|
}
|
||||||
log := *logger.New(logVerbosity, io.MultiWriter(fileLog), logSuppress)
|
log := logging.New(logVerbosity, io.MultiWriter(fileLog), logSuppress)
|
||||||
|
|
||||||
template := gocv.IMRead("images/template.jpg", gocv.IMReadGrayScale)
|
template := gocv.IMRead("images/template.jpg", gocv.IMReadGrayScale)
|
||||||
transformMatrix, err := FindTransform("images/default.jpg", "images/template.jpg")
|
transformMatrix, err := FindTransform("images/default.jpg", "images/template.jpg")
|
||||||
|
|
Loading…
Reference in New Issue