revid & cmd/revid-cli: added loop mode so that input may be restarted after completion

Loop flag has been added to command line flags and in turn sets the Loop field that has been
added to the config.Config struct. mode variable now also checked to see if value set to
Loop, in which case revid config.Config.Loop = true. Revid.processFrom modified so that
when input source has completed Revid.cfg.Loop is checked and input restarted if true.
This commit is contained in:
Saxon 2020-01-24 19:21:18 +10:30
parent c2329b3a3f
commit 99b931f948
3 changed files with 38 additions and 11 deletions

View File

@ -122,6 +122,7 @@ func handleFlags() config.Config {
httpAddressPtr = flag.String("HttpAddress", "", "Destination address of http posts") httpAddressPtr = flag.String("HttpAddress", "", "Destination address of http posts")
verticalFlipPtr = flag.Bool("VerticalFlip", false, "Flip video vertically: Yes, No") verticalFlipPtr = flag.Bool("VerticalFlip", false, "Flip video vertically: Yes, No")
horizontalFlipPtr = flag.Bool("HorizontalFlip", false, "Flip video horizontally: Yes, No") horizontalFlipPtr = flag.Bool("HorizontalFlip", false, "Flip video horizontally: Yes, No")
loopPtr = flag.Bool("Loop", false, "Loop video if EOF encountered: true, false")
bitratePtr = flag.Uint("Bitrate", 0, "Bitrate of recorded video") bitratePtr = flag.Uint("Bitrate", 0, "Bitrate of recorded video")
heightPtr = flag.Uint("Height", 0, "Height in pixels") heightPtr = flag.Uint("Height", 0, "Height in pixels")
widthPtr = flag.Uint("Width", 0, "Width in pixels") widthPtr = flag.Uint("Width", 0, "Width in pixels")
@ -179,6 +180,8 @@ func handleFlags() config.Config {
} }
} }
cfg.Loop = *loopPtr
switch *inputPtr { switch *inputPtr {
case "Raspivid": case "Raspivid":
cfg.Input = config.InputRaspivid cfg.Input = config.InputRaspivid

View File

@ -297,6 +297,9 @@ type Config struct {
MOGMinArea float64 // Used to ignore small areas of motion detection. MOGMinArea float64 // Used to ignore small areas of motion detection.
MOGThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion. MOGThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
MOGHistory uint // Length of MOG filter's history MOGHistory uint // Length of MOG filter's history
// If true will restart reading of input after an io.EOF.
Loop bool
} }
// TypeData contains information about all of the variables that // TypeData contains information about all of the variables that

View File

@ -428,13 +428,8 @@ func (r *Revid) Start() error {
return err return err
} }
err = r.input.Start()
if err != nil {
return fmt.Errorf("could not start input device: %w", err)
}
r.wg.Add(1) r.wg.Add(1)
go r.processFrom(r.input, 0) go r.processFrom(r.input, (1000/25)*time.Millisecond)
r.running = true r.running = true
return nil return nil
@ -845,6 +840,11 @@ func (r *Revid) Update(vars map[string]string) error {
break break
} }
r.cfg.MOGHistory = uint(v) r.cfg.MOGHistory = uint(v)
case "mode":
r.cfg.Loop = false
if value == "Loop" {
r.cfg.Loop = true
}
} }
} }
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))
@ -853,14 +853,35 @@ func (r *Revid) Update(vars map[string]string) error {
// processFrom is run as a routine to read from a input data source, lex and // processFrom is run as a routine to read from a input data source, lex and
// then send individual access units to revid's encoders. // then send individual access units to revid's encoders.
func (r *Revid) processFrom(read io.Reader, delay time.Duration) { func (r *Revid) processFrom(in device.AVDevice, delay time.Duration) {
err := r.lexTo(r.filters[0], read, delay) restart:
r.cfg.Logger.Log(logger.Debug, pkg+"finished lexing") err := in.Start()
if err != nil {
r.err <- fmt.Errorf("could not start input device: %w", err)
r.wg.Done()
return
}
// 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
// in this call indefinitely unless in.Stop() is called and an io.EOF is forced.
err = r.lexTo(r.filters[0], in, delay)
switch err { switch err {
case nil: // Do nothing. case nil, io.EOF, io.ErrUnexpectedEOF:
case io.EOF: // TODO: handle this depending on loop mode.
default: default:
r.err <- err r.err <- err
} }
err = in.Stop()
if err != nil {
r.err <- fmt.Errorf("could not stop input source: %w", err)
}
if r.cfg.Loop {
r.cfg.Logger.Log(logger.Info, pkg+"looping input")
goto restart
}
r.cfg.Logger.Log(logger.Info, pkg+"finished lexing")
r.wg.Done() r.wg.Done()
} }