revid: clean up input handling

This commit is contained in:
Dan Kortschak 2018-06-24 21:31:09 +09:30
parent 4fc6e69b12
commit 647641bed6
1 changed files with 49 additions and 59 deletions

View File

@ -36,7 +36,6 @@ import (
"io" "io"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strconv" "strconv"
"time" "time"
@ -88,7 +87,6 @@ type Revid struct {
ringBuffer *ring.Buffer ringBuffer *ring.Buffer
config Config config Config
isRunning bool isRunning bool
inputFile *os.File
generator generator.Generator generator generator.Generator
parser parser.Parser parser parser.Parser
cmd *exec.Cmd cmd *exec.Cmd
@ -172,7 +170,7 @@ func (r *Revid) reset(config Config) error {
switch r.config.Input { switch r.config.Input {
case Raspivid: case Raspivid:
r.setupInput = r.setupInputForRaspivid r.setupInput = r.startRaspivid
case File: case File:
r.setupInput = r.setupInputForFile r.setupInput = r.setupInputForFile
} }
@ -432,13 +430,14 @@ func (r *Revid) outputClips() {
} }
} }
// setupInputForRaspivid sets up things for input from raspivid i.e. starts // startRaspivid sets up things for input from raspivid i.e. starts
// a raspivid process and pipes it's data output. // a raspivid process and pipes it's data output.
func (r *Revid) setupInputForRaspivid() error { func (r *Revid) startRaspivid() error {
r.Log(Info, "Starting raspivid!") r.Log(Info, "Starting raspivid!")
switch r.config.InputCodec { switch r.config.InputCodec {
case H264: case H264:
arguments := []string{"-cd", "H264", args := []string{
"-cd", "H264",
"-o", "-", "-o", "-",
"-n", "-n",
"-t", r.config.Timeout, "-t", r.config.Timeout,
@ -449,33 +448,18 @@ func (r *Revid) setupInputForRaspivid() error {
"-ih", "-ih",
"-g", r.config.IntraRefreshPeriod, "-g", r.config.IntraRefreshPeriod,
} }
if r.config.QuantizationMode == QuantizationOn { if r.config.QuantizationMode == QuantizationOn {
arguments = append(arguments, "-qp") args = append(args, "-qp", r.config.Quantization)
arguments = append(arguments, r.config.Quantization)
} }
if r.config.HorizontalFlip == Yes { if r.config.HorizontalFlip == Yes {
arguments = append(arguments, "-hf") args = append(args, "-hf")
}
if r.config.VerticalFlip == Yes {
args = append(args, "-vf")
} }
if r.config.VerticalFlip == Yes { r.Log(Info, fmt.Sprintf("Starting raspivid with args: %v", args))
arguments = append(arguments, "-vf") r.cmd = exec.Command("raspivid", args...)
}
name := "raspivid"
r.cmd = &exec.Cmd{
Path: name,
Args: append([]string{name}, arguments...),
}
r.Log(Info, fmt.Sprintf("Startin raspivid with args: %v", r.cmd.Args))
if filepath.Base(name) == name {
if lp, err := exec.LookPath(name); err != nil {
r.Log(Error, err.Error())
return err
} else {
r.cmd.Path = lp
}
}
case Mjpeg: case Mjpeg:
r.cmd = exec.Command("raspivid", r.cmd = exec.Command("raspivid",
@ -486,31 +470,29 @@ func (r *Revid) setupInputForRaspivid() error {
"-fps", r.config.FrameRate, "-fps", r.config.FrameRate,
) )
} }
stdout, _ := r.cmd.StdoutPipe() stdout, err := r.cmd.StdoutPipe()
go r.cmd.Run() if err != nil {
return err
}
err = r.cmd.Start()
if err != nil {
return err
}
r.inputReader = bufio.NewReader(stdout) r.inputReader = bufio.NewReader(stdout)
go r.readCamera() go r.readCamera()
return nil return nil
} }
// setupInputForFile sets things up for getting input from a file
func (r *Revid) setupInputForFile() error {
fps, _ := strconv.Atoi(r.config.FrameRate)
r.parser.SetDelay(uint(float64(1000) / float64(fps)))
r.readFile()
return nil
}
// readCamera reads data from the defined camera while the Revid is running. // readCamera reads data from the defined camera while the Revid is running.
// TODO: use ringbuffer here instead of allocating mem every time! // TODO: use ringbuffer here instead of allocating mem every time!
func (r *Revid) readCamera() { func (r *Revid) readCamera() {
r.Log(Info, "Reading camera data!") r.Log(Info, "Reading camera data!")
for r.isRunning { for r.isRunning {
data := make([]byte, 1) var data [1]byte
_, err := io.ReadFull(r.inputReader, data) _, err := io.ReadFull(r.inputReader, data[:])
switch { switch {
// We know this means we're getting nothing from the cam // We know this means we're getting nothing from the cam
case (err != nil && err.Error() == "EOF" && r.isRunning) || (err != nil && r.isRunning): case err != nil && r.isRunning:
r.Log(Error, "No data from camera!") r.Log(Error, "No data from camera!")
time.Sleep(cameraRetryPeriod) time.Sleep(cameraRetryPeriod)
default: default:
@ -520,31 +502,39 @@ func (r *Revid) readCamera() {
r.Log(Info, "Not trying to read from camera anymore!") r.Log(Info, "Not trying to read from camera anymore!")
} }
// setupInputForFile sets things up for getting input from a file
func (r *Revid) setupInputForFile() error {
fps, err := strconv.Atoi(r.config.FrameRate)
if err != nil {
return err
}
r.parser.SetDelay(uint(float64(1000) / float64(fps)))
return r.readFile()
}
// readFile reads data from the defined file while the Revid is running. // readFile reads data from the defined file while the Revid is running.
func (r *Revid) readFile() error { func (r *Revid) readFile() error {
var err error f, err := os.Open(r.config.InputFileName)
r.inputFile, err = os.Open(r.config.InputFileName)
if err != nil { if err != nil {
r.Log(Error, err.Error()) r.Log(Error, err.Error())
r.Stop() r.Stop()
return err return err
} }
stats, err := r.inputFile.Stat() defer f.Close()
if err != nil { var buf [1 << 12]byte
r.Log(Error, "Could not get input file stats!") for {
r.Stop() n, err := f.Read(buf[:])
return err for _, b := range buf[:n] {
r.parser.InputChan() <- b
} }
data := make([]byte, stats.Size())
_, err = r.inputFile.Read(data)
if err != nil { if err != nil {
if err == io.EOF {
break
}
r.Log(Error, err.Error()) r.Log(Error, err.Error())
r.Stop() r.Stop()
return err return err
} }
for i := range data {
r.parser.InputChan() <- data[i]
} }
r.inputFile.Close()
return nil return nil
} }