mirror of https://bitbucket.org/ausocean/av.git
Improving error checking further
This commit is contained in:
parent
535d898a3c
commit
a07953042c
|
@ -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{
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue