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"
"os"
"os/exec"
"path/filepath"
"strconv"
"time"
@ -88,7 +87,6 @@ type Revid struct {
ringBuffer *ring.Buffer
config Config
isRunning bool
inputFile *os.File
generator generator.Generator
parser parser.Parser
cmd *exec.Cmd
@ -172,7 +170,7 @@ func (r *Revid) reset(config Config) error {
switch r.config.Input {
case Raspivid:
r.setupInput = r.setupInputForRaspivid
r.setupInput = r.startRaspivid
case File:
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.
func (r *Revid) setupInputForRaspivid() error {
func (r *Revid) startRaspivid() error {
r.Log(Info, "Starting raspivid!")
switch r.config.InputCodec {
case H264:
arguments := []string{"-cd", "H264",
args := []string{
"-cd", "H264",
"-o", "-",
"-n",
"-t", r.config.Timeout,
@ -449,33 +448,18 @@ func (r *Revid) setupInputForRaspivid() error {
"-ih",
"-g", r.config.IntraRefreshPeriod,
}
if r.config.QuantizationMode == QuantizationOn {
arguments = append(arguments, "-qp")
arguments = append(arguments, r.config.Quantization)
args = append(args, "-qp", r.config.Quantization)
}
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 {
arguments = append(arguments, "-vf")
}
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
}
}
r.Log(Info, fmt.Sprintf("Starting raspivid with args: %v", args))
r.cmd = exec.Command("raspivid", args...)
case Mjpeg:
r.cmd = exec.Command("raspivid",
@ -486,31 +470,29 @@ func (r *Revid) setupInputForRaspivid() error {
"-fps", r.config.FrameRate,
)
}
stdout, _ := r.cmd.StdoutPipe()
go r.cmd.Run()
stdout, err := r.cmd.StdoutPipe()
if err != nil {
return err
}
err = r.cmd.Start()
if err != nil {
return err
}
r.inputReader = bufio.NewReader(stdout)
go r.readCamera()
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.
// TODO: use ringbuffer here instead of allocating mem every time!
func (r *Revid) readCamera() {
r.Log(Info, "Reading camera data!")
for r.isRunning {
data := make([]byte, 1)
_, err := io.ReadFull(r.inputReader, data)
var data [1]byte
_, err := io.ReadFull(r.inputReader, data[:])
switch {
// 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!")
time.Sleep(cameraRetryPeriod)
default:
@ -520,31 +502,39 @@ func (r *Revid) readCamera() {
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.
func (r *Revid) readFile() error {
var err error
r.inputFile, err = os.Open(r.config.InputFileName)
f, err := os.Open(r.config.InputFileName)
if err != nil {
r.Log(Error, err.Error())
r.Stop()
return err
}
stats, err := r.inputFile.Stat()
if err != nil {
r.Log(Error, "Could not get input file stats!")
r.Stop()
return err
defer f.Close()
var buf [1 << 12]byte
for {
n, err := f.Read(buf[:])
for _, b := range buf[:n] {
r.parser.InputChan() <- b
}
if err != nil {
if err == io.EOF {
break
}
r.Log(Error, err.Error())
r.Stop()
return err
}
}
data := make([]byte, stats.Size())
_, err = r.inputFile.Read(data)
if err != nil {
r.Log(Error, err.Error())
r.Stop()
return err
}
for i := range data {
r.parser.InputChan() <- data[i]
}
r.inputFile.Close()
return nil
}