Improving error checking further

This commit is contained in:
Unknown 2018-01-31 11:30:03 +10:30
parent 535d898a3c
commit a07953042c
2 changed files with 117 additions and 90 deletions

View File

@ -32,6 +32,7 @@ package revid
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
@ -41,7 +42,6 @@ import (
"os/exec"
"strconv"
"time"
"errors"
//"bitbucket.org/ausocean/av/h264"
//"bitbucket.org/ausocean/av/tsgenerator"
@ -50,25 +50,25 @@ import (
//"bitbucket.org/ausocean/av/ringbuffer"
//"bitbucket.org/ausocean/utils/smartLogger"
"../ringbuffer"
"../../utils/smartLogger"
"../ringbuffer"
)
// Misc constants
const (
clipDuration = 1 // s
mp2tPacketSize = 188 // MPEG-TS packet size
mp2tMaxPackets = 2016 * clipDuration // # first multiple of 7 and 8 greater than 2000
udpPackets = 7 // # of UDP packets per ethernet frame (8 is the max)
rtpPackets = 7 // # of RTP packets per ethernet frame (7 is the max)
rtpHeaderSize = 12
rtpSSRC = 1 // any value will do
bufferSize = 100 / clipDuration
httpTimeOut = 5 // s
packetsPerFrame = 7
h264BufferSize = 500000
bitrateTime = 60
mjpegParserInChanLen= 10000
clipDuration = 1 // s
mp2tPacketSize = 188 // MPEG-TS packet size
mp2tMaxPackets = 2016 * clipDuration // # first multiple of 7 and 8 greater than 2000
udpPackets = 7 // # of UDP packets per ethernet frame (8 is the max)
rtpPackets = 7 // # of RTP packets per ethernet frame (7 is the max)
rtpHeaderSize = 12
rtpSSRC = 1 // any value will do
bufferSize = 100 / clipDuration
httpTimeOut = 5 // s
packetsPerFrame = 7
h264BufferSize = 500000
bitrateTime = 60
mjpegParserInChanLen = 10000
)
// Log Types
@ -82,40 +82,41 @@ const (
// Config provides parameters relevant to a revid instance. A new config must
// be passed to the constructor.
type Config struct {
Input uint8
InputCodec uint8
Output uint8
OutputFileName string
InputFileName string
Height string
Width string
FrameRate string
HttpAddress string
Quantization string
Timeout string
Packetization uint8
Input uint8
InputCodec uint8
Output uint8
OutputFileName string
InputFileName string
Height string
Width string
FrameRate string
HttpAddress string
Quantization string
Timeout string
Packetization uint8
IntraRefreshPeriod string
Logger smartLogger.LogInstance
Logger smartLogger.LogInstance
}
// Enums for config struct
const (
raspivid = 1
rtp = 2
h264Codec = 3
file = 4
httpOut = 5
h264 = 6
mjpeg = 7
none = 8
mpegts = 9
NothingDefined = 0
Raspivid = 1
Rtp = 2
H264Codec = 3
File = 4
HttpOut = 5
H264 = 6
Mjpeg = 7
None = 8
Mpegts = 9
)
// Default config settings
const (
defaultFrameRate = "25"
defaultWidth = "1280"
defaultHeight = "720"
defaultFrameRate = "25"
defaultWidth = "1280"
defaultHeight = "720"
defaultIntraRefreshPeriod = "100"
)
@ -130,20 +131,19 @@ type RevidInst interface {
IsRunning() bool
}
// The revidInst struct provides fields to describe the state of a RevidInst.
type revidInst struct {
ffmpegPath string
tempDir string
ringBuffer ringbuffer.RingBuffer
config Config
isRunning bool
outputFile *os.File
inputFile *os.File
generator tsgenerator.TsGenerator
parser parser.Parser
cmd *exec.Cmd
inputReader *bufio.Reader
ffmpegPath string
tempDir string
ringBuffer ringbuffer.RingBuffer
config Config
isRunning bool
outputFile *os.File
inputFile *os.File
generator tsgenerator.TsGenerator
parser parser.Parser
cmd *exec.Cmd
inputReader *bufio.Reader
mjpegOutputChan chan []byte
}
@ -198,50 +198,67 @@ func (r *revidInst) GetConfigRef() *Config {
// ChangeState swaps the current config of a revidInst with the passed
// configuration; checking validity and returning errors if not valid.
func (r *revidInst) ChangeState(config Config) error {
r.config.Logger = config.Logger
switch config.Input {
case rtp:
case raspivid:
case file:
case Rtp:
case Raspivid:
case File:
case NothingDefined:
r.Log(Warning, "No input type defined, defaulting to raspivid!")
config.Input = Raspivid
default:
return errors.New("Bad input type defined in config!")
}
switch config.InputCodec {
case h264:
case mjpeg:
case H264:
case Mjpeg:
case NothingDefined:
r.Log(Warning,"No input codec defined, defaulting to h264!")
config.InputCodec = H264
default:
return errors.New("Bad input format defined in config!")
return errors.New("Bad input codec defined in config!")
}
switch config.Output {
case httpOut:
case file:
case HttpOut:
case File:
case NothingDefine:
r.Log(Warning, "No output defined, defaulting to httpOut!")
config.Output = HttpOut
default:
return errors.New("Bad output type defined in config!")
}
if integer, err := strconv.Atoi(config.Width); integer < 0 || err != nil {
return errors.New("Bad width defined in config!")
}
if integer, _ := strconv.Atoi(config.Width); integer == 0 {
r.Log(Warning, "No width defined, defaulting to 1280!")
config.Width = defaultWidth
}
if integer, err := strconv.Atoi(config.Height); integer < 0 || err != nil {
return errors.New("Bad height defined in config!")
}
if integer, _ := strconv.Atoi(config.Height); integer == 0 {
r.Log(Warning, "No height defined, defaulting to 720!")
config.Height = defaultHeight
}
if integer, err := strconv.Atoi(config.FrameRate); integer < 0 || err != nil {
return errors.New("Bad FrameRate defined in config!")
}
if integer, _ := strconv.Atoi(config.FrameRate); integer == 0 {
r.Log(Warning, "No FrameRate defined, defaulting to 25!")
config.FrameRate = defaultFrameRate
}
if integer, err := strconv.Atoi(config.Timeout); integer < 0 || err != nil {
return errors.New("Bad timeout define in config!")
return errors.New("Bad timeout defined in config!")
}
if integer, err := strconv.Atoi(config.IntraRefreshPeriod); integer < 0 || err != nil {
return errors.New("Bad intra refresh period defined in config!")
}
if integer, _ := strconv.Atoi(config.IntraRefreshPeriod); integer == 0 {
r.Log(Warning, "No intra refresh period defined, defaulting to 100!")
config.IntraRefreshPeriod = defaultIntraRefreshPeriod
}
if integer, err := strconv.Atoi(config.Quantization); integer <= 0 || integer > 51 || err != nil {
@ -280,24 +297,24 @@ func (r *revidInst) Start() {
case raspivid:
r.Log(Info, "Starting raspivid!")
var codec string
switch r.config.InputCodec{
switch r.config.InputCodec {
case h264:
codec = "H264"
case mjpeg:
codec = "MJPEG"
}
r.cmd = exec.Command("raspivid",
"-cd", codec,
"-o", "-",
"-cd", codec,
"-o", "-",
"-n",
"-t", r.config.Timeout,
"-b", "0",
"-qp", r.config.Quantization,
"-w", r.config.Width,
"-h", r.config.Height,
"-t", r.config.Timeout,
"-b", "0",
"-qp", r.config.Quantization,
"-w", r.config.Width,
"-h", r.config.Height,
"-fps", r.config.FrameRate,
"-ih",
"-g", r.config.IntraRefreshPeriod,
"-g", r.config.IntraRefreshPeriod,
)
stdout, _ := r.cmd.StdoutPipe()
err := r.cmd.Start()
@ -330,7 +347,7 @@ func (r *revidInst) Start() {
}
// readCamera reads data from the defined camera while the revidInst is running.
func (r *revidInst)readCamera() {
func (r *revidInst) readCamera() {
r.Log(Info, "Reading camera data!")
for r.isRunning {
data := make([]byte, 1)
@ -342,7 +359,7 @@ func (r *revidInst)readCamera() {
case err != nil && r.isRunning:
r.Log(Error, err.Error())
default:
r.parser.GetInputChan()<-data[0]
r.parser.GetInputChan() <- data[0]
}
}
r.Log(Info, "Out of reading routine!")
@ -391,7 +408,7 @@ func (r *revidInst) packClips() {
frame := <-r.mjpegOutputChan
upperBound := clipSize + len(frame)
copy(clip[clipSize:upperBound], frame)
packetCount ++
packetCount++
clipSize += len(frame)
case mpegts:
tsPacket := <-(r.generator.GetTsOutputChan())
@ -467,7 +484,7 @@ func (r *revidInst) outputClips() {
}
}
// sendClipToHTTP takes a clip and an output url and posts through http.
// sendClipToHTTP takes a clip and an output url and posts through http.
func (r *revidInst) sendClipToHTTP(clip []byte, output string) error {
timeout := time.Duration(httpTimeOut * time.Second)
client := http.Client{

View File

@ -33,16 +33,12 @@ import (
"time"
)
/*
* Testing with file input
*
*/
/*
// Test revidInst with a file input
func TestFileInput(t *testing.T){
config := Config{
Input: file,
Input: file,
InputFileName: "testInput.h264",
Output: file,
Output: file,
OutputFileName: "output/TestFileAsInput.ts",
}
revidInst, err := NewRevidInstance(config)
@ -53,13 +49,9 @@ func TestFileInput(t *testing.T){
time.Sleep(100*time.Second)
revidInst.Stop()
}
* */
/*
Testing use with raspivid
*/
func TestRaspividInput(t *testing.T){
// Test revidInst with a Raspivid h264 input
func TestRaspividH264Input(t *testing.T){
config := Config{
Input: Raspivid,
Output: File,
@ -78,6 +70,24 @@ func TestRaspividInput(t *testing.T){
revidInst.Stop()
}
// Test revidInst with a raspivid mjpeg input
func TestRaspividMJPEGInput(t *testing.T){
config := Config{
Input: Raspivid,
InputCodec: mjpeg,
Output: File,
OutputFileName: "output/TestRaspividMjpegOutput.mjpeg",
Width: "1280",
Height: "720",
Bitrate: "0",
Quantization: "35",
FrameRate: "25",
}
revidInst, err := NewRevidInstance(config)
if err != nil {
t.Errorf("Should not of have got an error!")
}
revidInst.Start()
time.Sleep(100*time.Second)
revidInst.Stop()
}