diff --git a/device/raspivid/raspivid.go b/device/raspivid/raspivid.go index 44ead430..2b588aeb 100644 --- a/device/raspivid/raspivid.go +++ b/device/raspivid/raspivid.go @@ -28,6 +28,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "os/exec" "strings" @@ -106,14 +107,20 @@ var AutoWhiteBalanceModes = [...]string{ // Raspivid is an implementation of AVDevice that provides control over the // raspivid command to allow reading of data from a Raspberry Pi camera. type Raspivid struct { - cfg config.Config - cmd *exec.Cmd - out io.ReadCloser - log config.Logger + cfg config.Config + cmd *exec.Cmd + out io.ReadCloser + log config.Logger + done chan struct{} } // New returns a new Raspivid. -func New(l config.Logger) *Raspivid { return &Raspivid{log: l} } +func New(l config.Logger) *Raspivid { + return &Raspivid{ + log: l, + done: make(chan struct{}), + } +} // Name returns the name of the device. func (r *Raspivid) Name() string { @@ -250,6 +257,32 @@ func (r *Raspivid) Start() error { return fmt.Errorf("could not pipe command output: %w", err) } + stderr, err := r.cmd.StderrPipe() + if err != nil { + return fmt.Errorf("could not pipe command error: %w", err) + } + + go func() { + for { + select { + case <-r.done: + r.cfg.Logger.Log(logger.Info, "raspivid.Stop() called, finished checking stderr") + return + default: + buf, err := ioutil.ReadAll(stderr) + if err != nil { + r.cfg.Logger.Log(logger.Error, "could not read stderr", "error", err) + return + } + + if len(buf) != 0 { + r.cfg.Logger.Log(logger.Error, "error from raspivid stderr", "error", string(buf)) + return + } + } + } + }() + err = r.cmd.Start() if err != nil { return fmt.Errorf("could not start raspivid command: %w", err) @@ -269,6 +302,7 @@ func (r *Raspivid) Read(p []byte) (int, error) { // Stop will terminate the raspivid process and close the output pipe. func (r *Raspivid) Stop() error { + close(r.done) if r.cmd == nil || r.cmd.Process == nil { return errors.New("raspivid process was never started") }