mirror of https://bitbucket.org/ausocean/av.git
filter: combine common filter variables
This commit is contained in:
parent
bb5618f3c7
commit
5f02bb3829
|
@ -34,6 +34,13 @@ import (
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultBasicThreshold = 45000
|
||||||
|
defaultBasicPixels = 1000
|
||||||
)
|
)
|
||||||
|
|
||||||
type pixel struct{ r, g, b uint32 }
|
type pixel struct{ r, g, b uint32 }
|
||||||
|
@ -54,11 +61,22 @@ type Basic struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBasic returns a pointer to a new Basic filter 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{
|
return &Basic{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
thresh: t,
|
thresh: int(c.MotionThreshold),
|
||||||
pix: p,
|
pix: c.MotionPixels,
|
||||||
debugging: newWindows("BASIC"),
|
debugging: newWindows("BASIC"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"gocv.io/x/gocv"
|
"gocv.io/x/gocv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultDiffThreshold = 3
|
||||||
|
|
||||||
// Difference is a filter that provides basic motion detection. Difference calculates
|
// 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 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.
|
// 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.
|
// 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{
|
return &Difference{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
thresh: threshold,
|
thresh: c.MotionThreshold,
|
||||||
prev: gocv.NewMat(),
|
prev: gocv.NewMat(),
|
||||||
debugging: newWindows("DIFF"),
|
debugging: newWindows("DIFF"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,20 +30,22 @@ package filter
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewMOG returns a pointer to a new NoOp struct for testing purposes only.
|
// 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}
|
return &NoOp{dst: dst}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKNN returns a pointer to a new NoOp struct for testing purposes only.
|
// 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}
|
return &NoOp{dst: dst}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDiffference returns a pointer to a new NoOp struct for testing purposes only.
|
// 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}
|
return &NoOp{dst: dst}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,19 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"gocv.io/x/gocv"
|
"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
|
// KNN is a filter that provides basic motion detection. KNN is short for
|
||||||
// K-Nearest Neighbours method.
|
// K-Nearest Neighbours method.
|
||||||
type KNN struct {
|
type KNN struct {
|
||||||
|
@ -51,17 +61,44 @@ type KNN struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKNN returns a pointer to a new KNN filter 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 {
|
func NewKNN(dst io.WriteCloser, c config.Config) *KNN {
|
||||||
bs := gocv.NewBackgroundSubtractorKNNWithParams(history, threshold, false)
|
// Validate parameters.
|
||||||
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(kernelSize, kernelSize))
|
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{
|
return &KNN{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
area: area,
|
area: c.MotionMinArea,
|
||||||
bs: &bs,
|
bs: &bs,
|
||||||
knl: k,
|
knl: k,
|
||||||
hold: make([][]byte, hf-1),
|
hold: make([][]byte, c.MotionInterval-1),
|
||||||
hf: hf,
|
hf: c.MotionInterval,
|
||||||
scale: 1 / float64(scaleFactor),
|
scale: 1 / float64(c.MotionDownscaling),
|
||||||
debugging: newWindows("KNN"),
|
debugging: newWindows("KNN"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,19 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/av/revid/config"
|
||||||
"gocv.io/x/gocv"
|
"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
|
// MOG is a filter that provides basic motion detection. MoG is short for
|
||||||
// Mixture of Gaussians method.
|
// Mixture of Gaussians method.
|
||||||
type MOG struct {
|
type MOG struct {
|
||||||
|
@ -51,17 +61,43 @@ type MOG struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMOG returns a pointer to a new MOG filter 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 {
|
func NewMOG(dst io.WriteCloser, c config.Config) *MOG {
|
||||||
bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false)
|
// 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))
|
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3))
|
||||||
return &MOG{
|
return &MOG{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
area: area,
|
area: c.MotionMinArea,
|
||||||
bs: &bs,
|
bs: &bs,
|
||||||
knl: k,
|
knl: k,
|
||||||
hold: make([][]byte, hf-1),
|
hold: make([][]byte, c.MotionInterval-1),
|
||||||
hf: hf,
|
hf: c.MotionInterval,
|
||||||
scale: 1 / float64(scaleFactor),
|
scale: 1 / float64(c.MotionDownscaling),
|
||||||
debugging: newWindows("MOG"),
|
debugging: newWindows("MOG"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,24 +91,7 @@ const (
|
||||||
defaultRBWriteTimeout = 5
|
defaultRBWriteTimeout = 5
|
||||||
|
|
||||||
// Motion filter parameter defaults.
|
// Motion filter parameter defaults.
|
||||||
defaultMinFPS = 1.0
|
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.
|
// Quality represents video quality.
|
||||||
|
@ -283,27 +266,16 @@ type Config struct {
|
||||||
RBWriteTimeout int // The ringbuffer write timeout in seconds.
|
RBWriteTimeout int // The ringbuffer write timeout in seconds.
|
||||||
|
|
||||||
// Motion filter parameters.
|
// 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.
|
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.
|
MotionDownscaling int // Downscaling factor of frames used for motion detection.
|
||||||
|
|
||||||
// KNN filter parameters.
|
MotionMinArea float64 // Used to ignore small areas of motion detection (KNN & MOG only).
|
||||||
KNNMinArea float64 // Used to ignore small areas of motion detection.
|
MotionThreshold float64 // Intensity value that is considered motion.
|
||||||
KNNThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
|
MotionHistory uint // Length of filter's history (KNN & MOG only).
|
||||||
KNNHistory uint // Length of KNN filter's history
|
MotionKernel uint // Size of kernel used for filling holes and removing noise (KNN only).
|
||||||
KNNKernel uint // Size of kernel used for filling holes and removing noise.
|
MotionPixels int // Number of pixels with motion that is needed for a whole frame to be considered as moving (Basic only).
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// If true will restart reading of input after an io.EOF.
|
// If true will restart reading of input after an io.EOF.
|
||||||
Loop bool
|
Loop bool
|
||||||
|
@ -316,8 +288,6 @@ type Config struct {
|
||||||
// can be set over the web. It is a psuedo const.
|
// can be set over the web. It is a psuedo const.
|
||||||
var TypeData = map[string]string{
|
var TypeData = map[string]string{
|
||||||
"AutoWhiteBalance": "enum:off,auto,sun,cloud,shade,tungsten,fluorescent,incandescent,flash,horizon",
|
"AutoWhiteBalance": "enum:off,auto,sun,cloud,shade,tungsten,fluorescent,incandescent,flash,horizon",
|
||||||
"BasicPixels": "int",
|
|
||||||
"BasicThreshold": "int",
|
|
||||||
"BitDepth": "int",
|
"BitDepth": "int",
|
||||||
"Brightness": "uint",
|
"Brightness": "uint",
|
||||||
"BurstPeriod": "uint",
|
"BurstPeriod": "uint",
|
||||||
|
@ -325,7 +295,6 @@ var TypeData = map[string]string{
|
||||||
"CameraIP": "string",
|
"CameraIP": "string",
|
||||||
"CBR": "bool",
|
"CBR": "bool",
|
||||||
"ClipDuration": "uint",
|
"ClipDuration": "uint",
|
||||||
"DiffThreshold": "float",
|
|
||||||
"Exposure": "enum:auto,night,nightpreview,backlight,spotlight,sports,snow,beach,verylong,fixedfps,antishake,fireworks",
|
"Exposure": "enum:auto,night,nightpreview,backlight,spotlight,sports,snow,beach,verylong,fixedfps,antishake,fireworks",
|
||||||
"FileFPS": "int",
|
"FileFPS": "int",
|
||||||
"Filters": "enums:NoOp,MOG,VariableFPS,KNN,Difference,Basic",
|
"Filters": "enums:NoOp,MOG,VariableFPS,KNN,Difference,Basic",
|
||||||
|
@ -336,20 +305,18 @@ var TypeData = map[string]string{
|
||||||
"Input": "enum:raspivid,rtsp,v4l,file",
|
"Input": "enum:raspivid,rtsp,v4l,file",
|
||||||
"InputCodec": "enum:H264,MJPEG",
|
"InputCodec": "enum:H264,MJPEG",
|
||||||
"InputPath": "string",
|
"InputPath": "string",
|
||||||
"KNNHistory": "uint",
|
|
||||||
"KNNKernel": "float",
|
|
||||||
"KNNMinArea": "float",
|
|
||||||
"KNNThreshold": "float",
|
|
||||||
"logging": "enum:Debug,Info,Warning,Error,Fatal",
|
"logging": "enum:Debug,Info,Warning,Error,Fatal",
|
||||||
"Loop": "bool",
|
"Loop": "bool",
|
||||||
"MinFPS": "float",
|
"MinFPS": "float",
|
||||||
"MinFrames": "uint",
|
"MinFrames": "uint",
|
||||||
"mode": "enum:Normal,Paused,Burst,Loop",
|
"mode": "enum:Normal,Paused,Burst,Loop",
|
||||||
"MOGHistory": "uint",
|
|
||||||
"MOGMinArea": "float",
|
|
||||||
"MOGThreshold": "float",
|
|
||||||
"MotionDownscaling": "uint",
|
"MotionDownscaling": "uint",
|
||||||
|
"MotionHistory": "uint",
|
||||||
"MotionInterval": "int",
|
"MotionInterval": "int",
|
||||||
|
"MotionKernel": "uint",
|
||||||
|
"MotionMinArea": "float",
|
||||||
|
"MotionPixels": "int",
|
||||||
|
"MotionThreshold": "float",
|
||||||
"Output": "enum:File,Http,Rtmp,Rtp",
|
"Output": "enum:File,Http,Rtmp,Rtp",
|
||||||
"OutputPath": "string",
|
"OutputPath": "string",
|
||||||
"Outputs": "enums:File,Http,Rtmp,Rtp",
|
"Outputs": "enums:File,Http,Rtmp,Rtp",
|
||||||
|
@ -378,19 +345,19 @@ func (c *Config) Validate() error {
|
||||||
switch c.LogLevel {
|
switch c.LogLevel {
|
||||||
case logger.Debug, logger.Info, logger.Warning, logger.Error, logger.Fatal:
|
case logger.Debug, logger.Info, logger.Warning, logger.Error, logger.Fatal:
|
||||||
default:
|
default:
|
||||||
c.logInvalidField("LogLevel", defaultVerbosity)
|
c.LogInvalidField("LogLevel", defaultVerbosity)
|
||||||
c.LogLevel = defaultVerbosity
|
c.LogLevel = defaultVerbosity
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.CameraIP == "" {
|
if c.CameraIP == "" {
|
||||||
c.logInvalidField("CameraIP", defaultCameraIP)
|
c.LogInvalidField("CameraIP", defaultCameraIP)
|
||||||
c.CameraIP = defaultCameraIP
|
c.CameraIP = defaultCameraIP
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c.Input {
|
switch c.Input {
|
||||||
case InputRaspivid, InputV4L, InputFile, InputAudio, InputRTSP:
|
case InputRaspivid, InputV4L, InputFile, InputAudio, InputRTSP:
|
||||||
case NothingDefined:
|
case NothingDefined:
|
||||||
c.logInvalidField("Input", defaultInput)
|
c.LogInvalidField("Input", defaultInput)
|
||||||
c.Input = defaultInput
|
c.Input = defaultInput
|
||||||
default:
|
default:
|
||||||
return errors.New("bad input type defined in config")
|
return errors.New("bad input type defined in config")
|
||||||
|
@ -401,16 +368,16 @@ func (c *Config) Validate() error {
|
||||||
default:
|
default:
|
||||||
switch c.Input {
|
switch c.Input {
|
||||||
case OutputAudio:
|
case OutputAudio:
|
||||||
c.logInvalidField("InputCodec", defaultAudioInputCodec)
|
c.LogInvalidField("InputCodec", defaultAudioInputCodec)
|
||||||
c.InputCodec = defaultAudioInputCodec
|
c.InputCodec = defaultAudioInputCodec
|
||||||
default:
|
default:
|
||||||
c.logInvalidField("InputCodec", defaultInputCodec)
|
c.LogInvalidField("InputCodec", defaultInputCodec)
|
||||||
c.InputCodec = defaultInputCodec
|
c.InputCodec = defaultInputCodec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Outputs == nil {
|
if c.Outputs == nil {
|
||||||
c.logInvalidField("Outputs", defaultOutput)
|
c.LogInvalidField("Outputs", defaultOutput)
|
||||||
c.Outputs = append(c.Outputs, defaultOutput)
|
c.Outputs = append(c.Outputs, defaultOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,14 +395,14 @@ func (c *Config) Validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.BurstPeriod == 0 {
|
if c.BurstPeriod == 0 {
|
||||||
c.logInvalidField("BurstPeriod", defaultBurstPeriod)
|
c.LogInvalidField("BurstPeriod", defaultBurstPeriod)
|
||||||
c.BurstPeriod = defaultBurstPeriod
|
c.BurstPeriod = defaultBurstPeriod
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxMinFrames = 1000
|
const maxMinFrames = 1000
|
||||||
switch {
|
switch {
|
||||||
case c.MinFrames == 0:
|
case c.MinFrames == 0:
|
||||||
c.logInvalidField("MinFrames", defaultMinFrames)
|
c.LogInvalidField("MinFrames", defaultMinFrames)
|
||||||
c.MinFrames = defaultMinFrames
|
c.MinFrames = defaultMinFrames
|
||||||
case c.MinFrames < 0:
|
case c.MinFrames < 0:
|
||||||
return errors.New("refresh period is less than 0")
|
return errors.New("refresh period is less than 0")
|
||||||
|
@ -444,115 +411,60 @@ func (c *Config) Validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.FrameRate <= 0 {
|
if c.FrameRate <= 0 {
|
||||||
c.logInvalidField("FrameRate", defaultFrameRate)
|
c.LogInvalidField("FrameRate", defaultFrameRate)
|
||||||
c.FrameRate = defaultFrameRate
|
c.FrameRate = defaultFrameRate
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.WriteRate <= 0 {
|
if c.WriteRate <= 0 {
|
||||||
c.logInvalidField("writeRate", defaultWriteRate)
|
c.LogInvalidField("writeRate", defaultWriteRate)
|
||||||
c.WriteRate = defaultWriteRate
|
c.WriteRate = defaultWriteRate
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ClipDuration == 0 {
|
if c.ClipDuration == 0 {
|
||||||
c.logInvalidField("ClipDuration", defaultClipDuration)
|
c.LogInvalidField("ClipDuration", defaultClipDuration)
|
||||||
c.ClipDuration = defaultClipDuration
|
c.ClipDuration = defaultClipDuration
|
||||||
} else if c.ClipDuration < 0 {
|
} else if c.ClipDuration < 0 {
|
||||||
return errors.New("clip duration is less than 0")
|
return errors.New("clip duration is less than 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RTPAddress == "" {
|
if c.RTPAddress == "" {
|
||||||
c.logInvalidField("RTPAddress", defaultRtpAddr)
|
c.LogInvalidField("RTPAddress", defaultRtpAddr)
|
||||||
c.RTPAddress = defaultRtpAddr
|
c.RTPAddress = defaultRtpAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RBMaxElements <= 0 {
|
if c.RBMaxElements <= 0 {
|
||||||
c.logInvalidField("RBMaxElements", defaultRBMaxElements)
|
c.LogInvalidField("RBMaxElements", defaultRBMaxElements)
|
||||||
c.RBMaxElements = defaultRBMaxElements
|
c.RBMaxElements = defaultRBMaxElements
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RBCapacity <= 0 {
|
if c.RBCapacity <= 0 {
|
||||||
c.logInvalidField("RBCapacity", defaultRBCapacity)
|
c.LogInvalidField("RBCapacity", defaultRBCapacity)
|
||||||
c.RBCapacity = defaultRBCapacity
|
c.RBCapacity = defaultRBCapacity
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RBWriteTimeout <= 0 {
|
if c.RBWriteTimeout <= 0 {
|
||||||
c.logInvalidField("RBWriteTimeout", defaultRBWriteTimeout)
|
c.LogInvalidField("RBWriteTimeout", defaultRBWriteTimeout)
|
||||||
c.RBWriteTimeout = defaultRBWriteTimeout
|
c.RBWriteTimeout = defaultRBWriteTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.PSITime <= 0 {
|
if c.PSITime <= 0 {
|
||||||
c.logInvalidField("PSITime", defaultPSITime)
|
c.LogInvalidField("PSITime", defaultPSITime)
|
||||||
c.PSITime = defaultPSITime
|
c.PSITime = defaultPSITime
|
||||||
}
|
}
|
||||||
if c.MotionInterval <= 0 {
|
|
||||||
c.logInvalidField("MotionInterval", defaultMotionInterval)
|
|
||||||
c.MotionInterval = defaultMotionInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.MinFPS <= 0 {
|
if c.MinFPS <= 0 {
|
||||||
c.logInvalidField("MinFPS", defaultMinFPS)
|
c.LogInvalidField("MinFPS", defaultMinFPS)
|
||||||
c.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) {
|
if c.FileFPS <= 0 || (c.FileFPS > 0 && c.Input != InputFile) {
|
||||||
c.logInvalidField("FileFPS", defaultFileFPS)
|
c.LogInvalidField("FileFPS", defaultFileFPS)
|
||||||
c.FileFPS = defaultFileFPS
|
c.FileFPS = defaultFileFPS
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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)
|
c.Logger.Log(logger.Info, pkg+name+" bad or unset, defaulting", name, def)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,15 +334,15 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
case config.FilterNoOp:
|
case config.FilterNoOp:
|
||||||
r.filters[i] = filter.NewNoOp(dst)
|
r.filters[i] = filter.NewNoOp(dst)
|
||||||
case config.FilterMOG:
|
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:
|
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:
|
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:
|
case config.FilterDifference:
|
||||||
r.filters[i] = filter.NewDifference(dst, r.cfg.DiffThreshold)
|
r.filters[i] = filter.NewDifference(dst, r.cfg)
|
||||||
case config.FilterBasic:
|
case config.FilterBasic:
|
||||||
r.filters[i] = filter.NewBasic(dst, r.cfg.BasicThreshold, r.cfg.BasicPixels)
|
r.filters[i] = filter.NewBasic(dst, r.cfg)
|
||||||
default:
|
default:
|
||||||
panic("Undefined Filter")
|
panic("Undefined Filter")
|
||||||
}
|
}
|
||||||
|
@ -685,13 +685,6 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
}
|
}
|
||||||
r.cfg.Filters[i] = v
|
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":
|
case "PSITime":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil || v < 0 {
|
if err != nil || v < 0 {
|
||||||
|
@ -800,77 +793,55 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.MinFPS = v
|
r.cfg.MinFPS = v
|
||||||
case "KNNMinArea":
|
case "MotionMinArea":
|
||||||
v, err := strconv.ParseFloat(value, 64)
|
v, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
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
|
break
|
||||||
}
|
}
|
||||||
r.cfg.KNNMinArea = v
|
r.cfg.MotionMinArea = v
|
||||||
case "KNNThreshold":
|
case "MotionThreshold":
|
||||||
v, err := strconv.ParseFloat(value, 64)
|
v, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
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
|
break
|
||||||
}
|
}
|
||||||
r.cfg.KNNThreshold = v
|
r.cfg.MotionThreshold = v
|
||||||
case "DiffThreshold":
|
case "MotionKernel":
|
||||||
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":
|
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
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
|
break
|
||||||
}
|
}
|
||||||
r.cfg.KNNKernel = uint(v)
|
r.cfg.MotionKernel = uint(v)
|
||||||
case "MOGMinArea":
|
case "MotionHistory":
|
||||||
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":
|
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil || v <= 0 {
|
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
|
break
|
||||||
}
|
}
|
||||||
r.cfg.KNNHistory = uint(v)
|
r.cfg.MotionHistory = uint(v)
|
||||||
case "MOGHistory":
|
case "MotionPixels":
|
||||||
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":
|
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
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
|
break
|
||||||
}
|
}
|
||||||
r.cfg.BasicThreshold = v
|
r.cfg.MotionPixels = v
|
||||||
case "BasicPixels":
|
case "MotionDownscaling":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
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
|
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":
|
case "FileFPS":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -883,13 +854,6 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
if value == "Loop" {
|
if value == "Loop" {
|
||||||
r.cfg.Loop = true
|
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))
|
r.cfg.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.cfg))
|
||||||
|
|
Loading…
Reference in New Issue