From 99b931f948f875cb1b61d95aab8dc4670c9fd2e8 Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 24 Jan 2020 19:21:18 +1030 Subject: [PATCH] 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. --- cmd/revid-cli/main.go | 3 +++ revid/config/config.go | 3 +++ revid/revid.go | 43 +++++++++++++++++++++++++++++++----------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/cmd/revid-cli/main.go b/cmd/revid-cli/main.go index bced0a4f..fc4d863f 100644 --- a/cmd/revid-cli/main.go +++ b/cmd/revid-cli/main.go @@ -122,6 +122,7 @@ func handleFlags() config.Config { httpAddressPtr = flag.String("HttpAddress", "", "Destination address of http posts") verticalFlipPtr = flag.Bool("VerticalFlip", false, "Flip video vertically: 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") heightPtr = flag.Uint("Height", 0, "Height in pixels") widthPtr = flag.Uint("Width", 0, "Width in pixels") @@ -179,6 +180,8 @@ func handleFlags() config.Config { } } + cfg.Loop = *loopPtr + switch *inputPtr { case "Raspivid": cfg.Input = config.InputRaspivid diff --git a/revid/config/config.go b/revid/config/config.go index 194faf33..47a8eaf9 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -297,6 +297,9 @@ type Config struct { 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 + + // If true will restart reading of input after an io.EOF. + Loop bool } // TypeData contains information about all of the variables that diff --git a/revid/revid.go b/revid/revid.go index 8b1b42da..9c414480 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -428,13 +428,8 @@ func (r *Revid) Start() error { return err } - err = r.input.Start() - if err != nil { - return fmt.Errorf("could not start input device: %w", err) - } - r.wg.Add(1) - go r.processFrom(r.input, 0) + go r.processFrom(r.input, (1000/25)*time.Millisecond) r.running = true return nil @@ -845,6 +840,11 @@ func (r *Revid) Update(vars map[string]string) error { break } 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)) @@ -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 // then send individual access units to revid's encoders. -func (r *Revid) processFrom(read io.Reader, delay time.Duration) { - err := r.lexTo(r.filters[0], read, delay) - r.cfg.Logger.Log(logger.Debug, pkg+"finished lexing") +func (r *Revid) processFrom(in device.AVDevice, delay time.Duration) { +restart: + 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 { - case nil: // Do nothing. - case io.EOF: // TODO: handle this depending on loop mode. + case nil, io.EOF, io.ErrUnexpectedEOF: default: 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() }