diff --git a/revid/revid.go b/revid/revid.go index 1c5caac3..41e2080a 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -101,8 +101,11 @@ type Revid struct { // encoders will hold the multiWriteCloser that writes to encoders from the lexer. encoders io.WriteCloser - // isRunning is used to keep track of revid's running state between methods. - isRunning bool + // running is used to keep track of revid's running state between methods. + running bool + + // mu is used to protect isRunning during concurrent use. + mu sync.Mutex // wg will be used to wait for any processing routines to finish. wg sync.WaitGroup @@ -321,14 +324,17 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. // Start invokes a Revid to start processing video from a defined input // and packetising (if theres packetization) to a defined output. // -// Start is not safe for concurrent use. +// Start is safe for concurrent use. func (r *Revid) Start() error { - if r.isRunning { + if r.IsRunning() { r.config.Logger.Log(logger.Warning, pkg+"start called, but revid already running") return nil } + + r.mu.Lock() + defer r.mu.Unlock() + r.config.Logger.Log(logger.Info, pkg+"starting Revid") - r.isRunning = true err := r.reset(r.config) if err != nil { r.Stop() @@ -339,19 +345,23 @@ func (r *Revid) Start() error { r.Stop() return err } + r.running = true return nil } // Stop closes down the pipeline. This closes encoders and sender output routines, // connections, and/or files. // -// Stop is not safe for concurrent use. +// Stop is safe for concurrent use. func (r *Revid) Stop() { - if !r.isRunning { + if !r.IsRunning() { r.config.Logger.Log(logger.Warning, pkg+"stop called but revid isn't running") return } + r.mu.Lock() + defer r.mu.Unlock() + if r.closeInput != nil { err := r.closeInput() if err != nil { @@ -370,18 +380,26 @@ func (r *Revid) Stop() { r.cmd.Process.Kill() } r.wg.Wait() - r.isRunning = false + r.running = false +} + +func (r *Revid) IsRunning() bool { + r.mu.Lock() + defer r.mu.Unlock() + return r.running } // Update takes a map of variables and their values and edits the current config // if the variables are recognised as valid parameters. // -// Update is not safe for concurrent use. +// Update is safe for concurrent use. func (r *Revid) Update(vars map[string]string) error { - if r.isRunning { + if r.IsRunning() { r.Stop() } + r.mu.Lock() + defer r.mu.Unlock() //look through the vars and update revid where needed for key, value := range vars { switch key {