diff --git a/revid/config/config.go b/revid/config/config.go index b766c648..936e51ce 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -95,9 +95,23 @@ const ( defaultRTMPRBSize = 100 defaultRTMPRBElementSize = 300000 defaultRTMPRBWriteTimeout = 5 + + // Motion filter parameter defaults. + defaultMinFPS = 1.0 + + // 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 ) -// quality represents video quality. +// Quality represents video quality. type Quality int // The different video qualities that can be used for variable bitrate when @@ -277,6 +291,20 @@ type Config struct { MTSRBSize int // The number of elements in the MTS sender ringbuffer. MTSRBElementSize int // The element size in bytes of the MTS sender RingBuffer. MTSRBWriteTimeout int // The ringbuffer write timeout in seconds. + + // Motion filter parameters. + MinFPS float64 // The reduced framerate of the video when there is no motion. + + // 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 } // TypeData contains information about all of the variables that @@ -298,13 +326,21 @@ 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", + "MinFPS": "float", "MinFrames": "uint", + "MOGHistory": "uint", + "MOGMinArea": "float", + "MOGThreshold": "float", "MTSRBElementSize": "int", "MTSRBSize": "int", "MTSRBWriteTimeout": "int", - "OutputPath": "string", "Output": "enum:File,Http,Rtmp,Rtp", + "OutputPath": "string", "Outputs": "enums:File,Http,Rtmp,Rtp", "Quantization": "uint", "Rotation": "uint", @@ -453,6 +489,46 @@ func (c *Config) Validate() error { c.PSITime = defaultPSITime } + if c.MinFPS <= 0 { + c.Logger.Log(logger.Info, pkg+"MinFPS bad or unset, defaulting", "MinFPS", defaultMinFPS) + c.MinFPS = defaultMinFPS + } + + if c.KNNMinArea <= 0 { + c.Logger.Log(logger.Info, pkg+"KNNMinArea bad or unset, defaulting", "KNNMinArea", defaultKNNMinArea) + c.KNNMinArea = defaultKNNMinArea + } + + if c.KNNThreshold <= 0 { + c.Logger.Log(logger.Info, pkg+"KNNThreshold bad or unset, defaulting", "KNNThreshold", defaultKNNThreshold) + c.KNNThreshold = defaultKNNThreshold + } + + if c.KNNHistory == 0 { + c.Logger.Log(logger.Info, pkg+"KNNHistory bad or unset, defaulting", "KNNHistory", defaultKNNHistory) + c.KNNHistory = defaultKNNHistory + } + + if c.KNNKernel <= 0 { + c.Logger.Log(logger.Info, pkg+"KNNKernel bad or unset, defaulting", "KNNKernel", defaultKNNKernel) + c.KNNKernel = defaultKNNKernel + } + + if c.MOGMinArea <= 0 { + c.Logger.Log(logger.Info, pkg+"MOGMinArea bad or unset, defaulting", "MOGMinArea", defaultMOGMinArea) + c.MOGMinArea = defaultMOGMinArea + } + + if c.MOGThreshold <= 0 { + c.Logger.Log(logger.Info, pkg+"MOGThreshold bad or unset, defaulting", "MOGThreshold", defaultMOGThreshold) + c.MOGThreshold = defaultMOGThreshold + } + + if c.MOGHistory == 0 { + c.Logger.Log(logger.Info, pkg+"MOGHistory bad or unset, defaulting", "MOGHistory", defaultMOGHistory) + c.MOGHistory = defaultMOGHistory + } + if c.ShowWindows { os, err := osName() if err != nil { diff --git a/revid/revid.go b/revid/revid.go index 7b5d4f47..ebfdbe8b 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -76,24 +76,6 @@ const ( rtmpConnectionTimeout = 10 ) -// Motion filter parameters. -const minFPS = 1.0 - -// KNN specific parameters. -const ( - knnMinArea = 25.0 - knnThreshold = 300 - knnHistory = 300 - knnKernel = 9 -) - -// MOG specific parameters. -const ( - mogMinArea = 25.0 - mogThreshold = 20.0 - mogHistory = 500 -) - const pkg = "revid: " type Logger interface { @@ -360,11 +342,11 @@ 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.NewMOGFilter(dst, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows) + r.filters[i] = filter.NewMOGFilter(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.ShowWindows) case config.FilterVariableFPS: - r.filters[i] = filter.NewVariableFPSFilter(dst, minFPS, filter.NewMOGFilter(dst, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows)) + r.filters[i] = filter.NewVariableFPSFilter(dst, r.cfg.MinFPS, filter.NewMOGFilter(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.ShowWindows)) case config.FilterKNN: - r.filters[i] = filter.NewKNNFilter(dst, knnMinArea, knnThreshold, knnHistory, knnKernel, r.cfg.ShowWindows) + r.filters[i] = filter.NewKNNFilter(dst, r.cfg.KNNMinArea, r.cfg.KNNThreshold, int(r.cfg.KNNHistory), int(r.cfg.KNNKernel), r.cfg.ShowWindows) default: panic("Undefined Filter") } @@ -803,6 +785,62 @@ func (r *Revid) Update(vars map[string]string) error { r.cfg.Logger.Log(logger.Warning, pkg+"invalid ShowWindows var", "value", value) break } + case "MinFPS": + v, err := strconv.ParseFloat(value, 64) + if err != nil { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid MinFPS var", "value", value) + break + } + r.cfg.MinFPS = v + case "KNNMinArea": + v, err := strconv.ParseFloat(value, 64) + if err != nil { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNMinArea var", "value", value) + break + } + r.cfg.KNNMinArea = v + case "KNNThreshold": + v, err := strconv.ParseFloat(value, 64) + if err != nil { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNThreshold var", "value", value) + break + } + r.cfg.KNNThreshold = v + case "KNNKernel": + v, err := strconv.Atoi(value) + if err != nil { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNKernel 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": + v, err := strconv.Atoi(value) + if err != nil || v <= 0 { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNHistory 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) } } r.cfg.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.cfg))