Merged in combine-filter-var (pull request #375)

filter: combine common filter variables

Approved-by: Saxon Milton <saxon.milton@gmail.com>
This commit is contained in:
Scott Barnard 2020-02-08 05:30:37 +00:00 committed by Saxon Milton
commit a41033beb3
7 changed files with 185 additions and 207 deletions

View File

@ -34,6 +34,13 @@ import (
"image/jpeg"
"io"
"sync"
"bitbucket.org/ausocean/av/revid/config"
)
const (
defaultBasicThreshold = 45000
defaultBasicPixels = 1000
)
type pixel struct{ r, g, b uint32 }
@ -54,11 +61,22 @@ type Basic struct {
}
// NewBasic returns a pointer to a new Basic filter struct.
func NewBasic(dst io.WriteCloser, t, p int) *Basic {
func NewBasic(dst io.WriteCloser, c config.Config) *Basic {
// Validate parameters.
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultBasicThreshold)
c.MotionThreshold = defaultBasicThreshold
}
if c.MotionPixels <= 0 {
c.LogInvalidField("MotionPixels", defaultBasicPixels)
c.MotionPixels = defaultBasicPixels
}
return &Basic{
dst: dst,
thresh: t,
pix: p,
thresh: int(c.MotionThreshold),
pix: c.MotionPixels,
debugging: newWindows("BASIC"),
}
}

View File

@ -33,9 +33,12 @@ import (
"fmt"
"io"
"bitbucket.org/ausocean/av/revid/config"
"gocv.io/x/gocv"
)
const defaultDiffThreshold = 3
// Difference is a filter that provides basic motion detection. Difference calculates
// the absolute difference for each pixel between two frames, then finds the mean. If
// the mean is above a given threshold, then it is considered motion.
@ -47,10 +50,16 @@ type Difference struct {
}
// NewDifference returns a pointer to a new Difference struct.
func NewDifference(dst io.WriteCloser, threshold float64) *Difference {
func NewDifference(dst io.WriteCloser, c config.Config) *Difference {
// Validate parameters.
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultDiffThreshold)
c.MotionThreshold = defaultDiffThreshold
}
return &Difference{
dst: dst,
thresh: threshold,
thresh: c.MotionThreshold,
prev: gocv.NewMat(),
debugging: newWindows("DIFF"),
}

View File

@ -30,20 +30,22 @@ package filter
import (
"image"
"io"
"bitbucket.org/ausocean/av/revid/config"
)
// NewMOG returns a pointer to a new NoOp struct for testing purposes only.
func NewMOG(dst io.WriteCloser, area, threshold float64, history int, hf int, scaleFactor int) *NoOp {
func NewMOG(dst io.WriteCloser, c config.Config) *NoOp {
return &NoOp{dst: dst}
}
// NewKNN returns a pointer to a new NoOp struct for testing purposes only.
func NewKNN(dst io.WriteCloser, area, threshold float64, history, kernelSize int, hf int, scaleFactor int) *NoOp {
func NewKNN(dst io.WriteCloser, c config.Config) *NoOp {
return &NoOp{dst: dst}
}
// NewDiffference returns a pointer to a new NoOp struct for testing purposes only.
func NewDifference(dst io.WriteCloser, threshold float64) *NoOp {
func NewDifference(dst io.WriteCloser, c config.Config) *NoOp {
return &NoOp{dst: dst}
}

View File

@ -33,9 +33,19 @@ import (
"image"
"io"
"bitbucket.org/ausocean/av/revid/config"
"gocv.io/x/gocv"
)
const (
defaultKNNMinArea = 25.0
defaultKNNThreshold = 300
defaultKNNHistory = 300
defaultKNNKernel = 4
defaultKNNDownscaling = 2
defaultKNNInterval = 1
)
// KNN is a filter that provides basic motion detection. KNN is short for
// K-Nearest Neighbours method.
type KNN struct {
@ -51,17 +61,44 @@ type KNN struct {
}
// NewKNN returns a pointer to a new KNN filter struct.
func NewKNN(dst io.WriteCloser, area, threshold float64, history, kernelSize int, hf int, scaleFactor int) *KNN {
bs := gocv.NewBackgroundSubtractorKNNWithParams(history, threshold, false)
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(kernelSize, kernelSize))
func NewKNN(dst io.WriteCloser, c config.Config) *KNN {
// Validate parameters.
if c.MotionMinArea <= 0 {
c.LogInvalidField("MotionMinArea", defaultKNNMinArea)
c.MotionMinArea = defaultKNNMinArea
}
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultKNNThreshold)
c.MotionThreshold = defaultKNNThreshold
}
if c.MotionHistory == 0 {
c.LogInvalidField("MotionHistory", defaultKNNHistory)
c.MotionHistory = defaultKNNHistory
}
if c.MotionDownscaling <= 0 {
c.LogInvalidField("MotionDownscaling", defaultKNNDownscaling)
c.MotionDownscaling = defaultKNNDownscaling
}
if c.MotionInterval <= 0 {
c.LogInvalidField("MotionInterval", defaultKNNInterval)
c.MotionInterval = defaultKNNInterval
}
if c.MotionKernel <= 0 {
c.LogInvalidField("MotionKernel", defaultKNNKernel)
c.MotionKernel = defaultKNNKernel
}
bs := gocv.NewBackgroundSubtractorKNNWithParams(int(c.MotionHistory), c.MotionThreshold, false)
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(int(c.MotionKernel), int(c.MotionKernel)))
return &KNN{
dst: dst,
area: area,
area: c.MotionMinArea,
bs: &bs,
knl: k,
hold: make([][]byte, hf-1),
hf: hf,
scale: 1 / float64(scaleFactor),
hold: make([][]byte, c.MotionInterval-1),
hf: c.MotionInterval,
scale: 1 / float64(c.MotionDownscaling),
debugging: newWindows("KNN"),
}
}

View File

@ -33,9 +33,19 @@ import (
"image"
"io"
"bitbucket.org/ausocean/av/revid/config"
"gocv.io/x/gocv"
)
const (
defaultMOGMinArea = 25.0
defaultMOGThreshold = 20.0
defaultMOGHistory = 500
defaultMOGKernel = 3
defaultMOGDownscaling = 2
defaultMOGInterval = 1
)
// MOG is a filter that provides basic motion detection. MoG is short for
// Mixture of Gaussians method.
type MOG struct {
@ -51,17 +61,43 @@ type MOG struct {
}
// NewMOG returns a pointer to a new MOG filter struct.
func NewMOG(dst io.WriteCloser, area, threshold float64, history int, hf int, scaleFactor int) *MOG {
bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false)
func NewMOG(dst io.WriteCloser, c config.Config) *MOG {
// Validate parameters.
if c.MotionMinArea <= 0 {
c.LogInvalidField("MotionMinArea", defaultMOGMinArea)
c.MotionMinArea = defaultMOGMinArea
}
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultMOGThreshold)
c.MotionThreshold = defaultMOGThreshold
}
if c.MotionHistory == 0 {
c.LogInvalidField("MotionHistory", defaultMOGHistory)
c.MotionHistory = defaultMOGHistory
}
if c.MotionDownscaling <= 0 {
c.LogInvalidField("MotionDownscaling", defaultMOGDownscaling)
c.MotionDownscaling = defaultMOGDownscaling
}
if c.MotionInterval <= 0 {
c.LogInvalidField("MotionInterval", defaultMOGInterval)
c.MotionInterval = defaultMOGInterval
}
if c.MotionKernel <= 0 {
c.LogInvalidField("MotionKernel", defaultMOGKernel)
c.MotionKernel = defaultMOGKernel
}
bs := gocv.NewBackgroundSubtractorMOG2WithParams(int(c.MotionHistory), c.MotionThreshold, false)
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3))
return &MOG{
dst: dst,
area: area,
area: c.MotionMinArea,
bs: &bs,
knl: k,
hold: make([][]byte, hf-1),
hf: hf,
scale: 1 / float64(scaleFactor),
hold: make([][]byte, c.MotionInterval-1),
hf: c.MotionInterval,
scale: 1 / float64(c.MotionDownscaling),
debugging: newWindows("MOG"),
}
}

View File

@ -92,23 +92,6 @@ const (
// Motion filter parameter defaults.
defaultMinFPS = 1.0
defaultMotionDownscaling = 1
defaultMotionInterval = 1
// KNN filter parameter defaults.
defaultKNNMinArea = 25.0
defaultKNNThreshold = 300
defaultKNNHistory = 300
defaultKNNKernel = 9
// MOG filter parameter defaults.
defaultMOGMinArea = 25.0
defaultMOGThreshold = 20.0
defaultMOGHistory = 500
// Basic filter parameter defaults
defaultBasicThreshold = 45000
defaultBasicPixels = 1000
)
// Quality represents video quality.
@ -283,27 +266,16 @@ type Config struct {
RBWriteTimeout int // The ringbuffer write timeout in seconds.
// Motion filter parameters.
// Some parameters can be used with any filter, while others can only be used by a few.
MinFPS float64 // The reduced framerate of the video when there is no motion.
MotionInterval int // Sets the number of frames that are held before the filter is used (on the nth frame)
MotionInterval int // Sets the number of frames that are held before the filter is used (on the nth frame).
MotionDownscaling int // Downscaling factor of frames used for motion detection.
// KNN filter parameters.
KNNMinArea float64 // Used to ignore small areas of motion detection.
KNNThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
KNNHistory uint // Length of KNN filter's history
KNNKernel uint // Size of kernel used for filling holes and removing noise.
// MOG filter parameters.
MOGMinArea float64 // Used to ignore small areas of motion detection.
MOGThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
MOGHistory uint // Length of MOG filter's history.
// Difference filter parameters.
DiffThreshold float64 // Intensity value from the Difference motion detection algorithm that is considered motion.
// Basic filter parameters.
BasicThreshold int
BasicPixels int
MotionMinArea float64 // Used to ignore small areas of motion detection (KNN & MOG only).
MotionThreshold float64 // Intensity value that is considered motion.
MotionHistory uint // Length of filter's history (KNN & MOG only).
MotionKernel uint // Size of kernel used for filling holes and removing noise (KNN only).
MotionPixels int // Number of pixels with motion that is needed for a whole frame to be considered as moving (Basic only).
// If true will restart reading of input after an io.EOF.
Loop bool
@ -316,8 +288,6 @@ type Config struct {
// can be set over the web. It is a psuedo const.
var TypeData = map[string]string{
"AutoWhiteBalance": "enum:off,auto,sun,cloud,shade,tungsten,fluorescent,incandescent,flash,horizon",
"BasicPixels": "int",
"BasicThreshold": "int",
"BitDepth": "int",
"Brightness": "uint",
"BurstPeriod": "uint",
@ -325,7 +295,6 @@ var TypeData = map[string]string{
"CameraIP": "string",
"CBR": "bool",
"ClipDuration": "uint",
"DiffThreshold": "float",
"Exposure": "enum:auto,night,nightpreview,backlight,spotlight,sports,snow,beach,verylong,fixedfps,antishake,fireworks",
"FileFPS": "int",
"Filters": "enums:NoOp,MOG,VariableFPS,KNN,Difference,Basic",
@ -336,20 +305,18 @@ var TypeData = map[string]string{
"Input": "enum:raspivid,rtsp,v4l,file",
"InputCodec": "enum:H264,MJPEG",
"InputPath": "string",
"KNNHistory": "uint",
"KNNKernel": "float",
"KNNMinArea": "float",
"KNNThreshold": "float",
"logging": "enum:Debug,Info,Warning,Error,Fatal",
"Loop": "bool",
"MinFPS": "float",
"MinFrames": "uint",
"mode": "enum:Normal,Paused,Burst,Loop",
"MOGHistory": "uint",
"MOGMinArea": "float",
"MOGThreshold": "float",
"MotionDownscaling": "uint",
"MotionHistory": "uint",
"MotionInterval": "int",
"MotionKernel": "uint",
"MotionMinArea": "float",
"MotionPixels": "int",
"MotionThreshold": "float",
"Output": "enum:File,Http,Rtmp,Rtp",
"OutputPath": "string",
"Outputs": "enums:File,Http,Rtmp,Rtp",
@ -378,19 +345,19 @@ func (c *Config) Validate() error {
switch c.LogLevel {
case logger.Debug, logger.Info, logger.Warning, logger.Error, logger.Fatal:
default:
c.logInvalidField("LogLevel", defaultVerbosity)
c.LogInvalidField("LogLevel", defaultVerbosity)
c.LogLevel = defaultVerbosity
}
if c.CameraIP == "" {
c.logInvalidField("CameraIP", defaultCameraIP)
c.LogInvalidField("CameraIP", defaultCameraIP)
c.CameraIP = defaultCameraIP
}
switch c.Input {
case InputRaspivid, InputV4L, InputFile, InputAudio, InputRTSP:
case NothingDefined:
c.logInvalidField("Input", defaultInput)
c.LogInvalidField("Input", defaultInput)
c.Input = defaultInput
default:
return errors.New("bad input type defined in config")
@ -401,16 +368,16 @@ func (c *Config) Validate() error {
default:
switch c.Input {
case OutputAudio:
c.logInvalidField("InputCodec", defaultAudioInputCodec)
c.LogInvalidField("InputCodec", defaultAudioInputCodec)
c.InputCodec = defaultAudioInputCodec
default:
c.logInvalidField("InputCodec", defaultInputCodec)
c.LogInvalidField("InputCodec", defaultInputCodec)
c.InputCodec = defaultInputCodec
}
}
if c.Outputs == nil {
c.logInvalidField("Outputs", defaultOutput)
c.LogInvalidField("Outputs", defaultOutput)
c.Outputs = append(c.Outputs, defaultOutput)
}
@ -428,14 +395,14 @@ func (c *Config) Validate() error {
}
if c.BurstPeriod == 0 {
c.logInvalidField("BurstPeriod", defaultBurstPeriod)
c.LogInvalidField("BurstPeriod", defaultBurstPeriod)
c.BurstPeriod = defaultBurstPeriod
}
const maxMinFrames = 1000
switch {
case c.MinFrames == 0:
c.logInvalidField("MinFrames", defaultMinFrames)
c.LogInvalidField("MinFrames", defaultMinFrames)
c.MinFrames = defaultMinFrames
case c.MinFrames < 0:
return errors.New("refresh period is less than 0")
@ -444,115 +411,60 @@ func (c *Config) Validate() error {
}
if c.FrameRate <= 0 {
c.logInvalidField("FrameRate", defaultFrameRate)
c.LogInvalidField("FrameRate", defaultFrameRate)
c.FrameRate = defaultFrameRate
}
if c.WriteRate <= 0 {
c.logInvalidField("writeRate", defaultWriteRate)
c.LogInvalidField("writeRate", defaultWriteRate)
c.WriteRate = defaultWriteRate
}
if c.ClipDuration == 0 {
c.logInvalidField("ClipDuration", defaultClipDuration)
c.LogInvalidField("ClipDuration", defaultClipDuration)
c.ClipDuration = defaultClipDuration
} else if c.ClipDuration < 0 {
return errors.New("clip duration is less than 0")
}
if c.RTPAddress == "" {
c.logInvalidField("RTPAddress", defaultRtpAddr)
c.LogInvalidField("RTPAddress", defaultRtpAddr)
c.RTPAddress = defaultRtpAddr
}
if c.RBMaxElements <= 0 {
c.logInvalidField("RBMaxElements", defaultRBMaxElements)
c.LogInvalidField("RBMaxElements", defaultRBMaxElements)
c.RBMaxElements = defaultRBMaxElements
}
if c.RBCapacity <= 0 {
c.logInvalidField("RBCapacity", defaultRBCapacity)
c.LogInvalidField("RBCapacity", defaultRBCapacity)
c.RBCapacity = defaultRBCapacity
}
if c.RBWriteTimeout <= 0 {
c.logInvalidField("RBWriteTimeout", defaultRBWriteTimeout)
c.LogInvalidField("RBWriteTimeout", defaultRBWriteTimeout)
c.RBWriteTimeout = defaultRBWriteTimeout
}
if c.PSITime <= 0 {
c.logInvalidField("PSITime", defaultPSITime)
c.LogInvalidField("PSITime", defaultPSITime)
c.PSITime = defaultPSITime
}
if c.MotionInterval <= 0 {
c.logInvalidField("MotionInterval", defaultMotionInterval)
c.MotionInterval = defaultMotionInterval
}
if c.MinFPS <= 0 {
c.logInvalidField("MinFPS", defaultMinFPS)
c.LogInvalidField("MinFPS", defaultMinFPS)
c.MinFPS = defaultMinFPS
}
if c.KNNMinArea <= 0 {
c.logInvalidField("KNNMinArea", defaultKNNMinArea)
c.KNNMinArea = defaultKNNMinArea
}
if c.KNNThreshold <= 0 {
c.logInvalidField("KNNThreshold", defaultKNNThreshold)
c.KNNThreshold = defaultKNNThreshold
}
if c.KNNHistory == 0 {
c.logInvalidField("KNNHistory", defaultKNNHistory)
c.KNNHistory = defaultKNNHistory
}
if c.KNNKernel <= 0 {
c.logInvalidField("KNNKernel", defaultKNNKernel)
c.KNNKernel = defaultKNNKernel
}
if c.MOGMinArea <= 0 {
c.logInvalidField("MOGMinArea", defaultMOGMinArea)
c.MOGMinArea = defaultMOGMinArea
}
if c.MOGThreshold <= 0 {
c.logInvalidField("MOGThreshold", defaultMOGThreshold)
c.MOGThreshold = defaultMOGThreshold
}
if c.MOGHistory == 0 {
c.logInvalidField("MOGHistory", defaultMOGHistory)
c.MOGHistory = defaultMOGHistory
}
if c.BasicThreshold <= 0 {
c.logInvalidField("BasicThreshold", defaultBasicThreshold)
c.BasicThreshold = defaultBasicThreshold
}
if c.BasicPixels <= 0 {
c.logInvalidField("BasicPixels", defaultBasicPixels)
c.BasicPixels = defaultBasicPixels
}
if c.MotionDownscaling <= 0 {
c.logInvalidField("MotionDownscaling", defaultMotionDownscaling)
c.MotionDownscaling = defaultMotionDownscaling
}
if c.FileFPS <= 0 || (c.FileFPS > 0 && c.Input != InputFile) {
c.logInvalidField("FileFPS", defaultFileFPS)
c.LogInvalidField("FileFPS", defaultFileFPS)
c.FileFPS = defaultFileFPS
}
return nil
}
func (c *Config) logInvalidField(name string, def interface{}) {
func (c *Config) LogInvalidField(name string, def interface{}) {
c.Logger.Log(logger.Info, pkg+name+" bad or unset, defaulting", name, def)
}

View File

@ -334,15 +334,15 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
case config.FilterNoOp:
r.filters[i] = filter.NewNoOp(dst)
case config.FilterMOG:
r.filters[i] = filter.NewMOG(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.MotionInterval, r.cfg.MotionDownscaling)
r.filters[i] = filter.NewMOG(dst, r.cfg)
case config.FilterVariableFPS:
r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.MotionInterval, r.cfg.MotionDownscaling))
r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg))
case config.FilterKNN:
r.filters[i] = filter.NewKNN(dst, r.cfg.KNNMinArea, r.cfg.KNNThreshold, int(r.cfg.KNNHistory), int(r.cfg.KNNKernel), r.cfg.MotionInterval, r.cfg.MotionDownscaling)
r.filters[i] = filter.NewKNN(dst, r.cfg)
case config.FilterDifference:
r.filters[i] = filter.NewDifference(dst, r.cfg.DiffThreshold)
r.filters[i] = filter.NewDifference(dst, r.cfg)
case config.FilterBasic:
r.filters[i] = filter.NewBasic(dst, r.cfg.BasicThreshold, r.cfg.BasicPixels)
r.filters[i] = filter.NewBasic(dst, r.cfg)
default:
panic("Undefined Filter")
}
@ -685,13 +685,6 @@ func (r *Revid) Update(vars map[string]string) error {
}
r.cfg.Filters[i] = v
}
case "MotionInterval":
v, err := strconv.Atoi(value)
if err != nil || v < 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionInterval var", "value", value)
break
}
r.cfg.MotionInterval = v
case "PSITime":
v, err := strconv.Atoi(value)
if err != nil || v < 0 {
@ -800,77 +793,55 @@ func (r *Revid) Update(vars map[string]string) error {
break
}
r.cfg.MinFPS = v
case "KNNMinArea":
case "MotionMinArea":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNMinArea var", "value", value)
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionMinArea var", "value", value)
break
}
r.cfg.KNNMinArea = v
case "KNNThreshold":
r.cfg.MotionMinArea = v
case "MotionThreshold":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNThreshold var", "value", value)
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionThreshold var", "value", value)
break
}
r.cfg.KNNThreshold = v
case "DiffThreshold":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid DiffThreshold var", "value", value)
break
}
r.cfg.DiffThreshold = v
case "KNNKernel":
r.cfg.MotionThreshold = v
case "MotionKernel":
v, err := strconv.Atoi(value)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNKernel var", "value", value)
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionKernel var", "value", value)
break
}
r.cfg.KNNKernel = uint(v)
case "MOGMinArea":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MOGMinArea var", "value", value)
break
}
r.cfg.MOGMinArea = v
case "MOGThreshold":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MOGThreshold var", "value", value)
break
}
r.cfg.MOGThreshold = v
case "KNNHistory":
r.cfg.MotionKernel = uint(v)
case "MotionHistory":
v, err := strconv.Atoi(value)
if err != nil || v <= 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNHistory var", "value", value)
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionHistory var", "value", value)
break
}
r.cfg.KNNHistory = uint(v)
case "MOGHistory":
v, err := strconv.Atoi(value)
if err != nil || v <= 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MOGHistory var", "value", value)
break
}
r.cfg.MOGHistory = uint(v)
case "BasicThreshold":
r.cfg.MotionHistory = uint(v)
case "MotionPixels":
v, err := strconv.Atoi(value)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid BasicThreshold var", "value", value)
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionPixels var", "value", value)
break
}
r.cfg.BasicThreshold = v
case "BasicPixels":
r.cfg.MotionPixels = v
case "MotionDownscaling":
v, err := strconv.Atoi(value)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid BasicPixels var", "value", value)
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionDownscaling var", "value", value)
break
}
r.cfg.BasicPixels = v
r.cfg.MotionDownscaling = v
case "MotionInterval":
v, err := strconv.Atoi(value)
if err != nil || v < 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionInterval var", "value", value)
break
}
r.cfg.MotionInterval = v
case "FileFPS":
v, err := strconv.Atoi(value)
if err != nil {
@ -883,13 +854,6 @@ func (r *Revid) Update(vars map[string]string) error {
if value == "Loop" {
r.cfg.Loop = true
}
case "MotionDownscaling":
v, err := strconv.Atoi(value)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionDownscaling var", "value", value)
break
}
r.cfg.MotionDownscaling = v
}
}
r.cfg.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.cfg))