mirror of https://bitbucket.org/ausocean/av.git
Builds and bugs are out (for now)
Let's try testing on the pi next
This commit is contained in:
parent
7572968ad3
commit
147716ccab
|
@ -36,7 +36,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -114,6 +113,8 @@ const (
|
||||||
defaultWidth = "1280"
|
defaultWidth = "1280"
|
||||||
defaultHeight = "720"
|
defaultHeight = "720"
|
||||||
defaultIntraRefreshPeriod = "100"
|
defaultIntraRefreshPeriod = "100"
|
||||||
|
defaultTimeout = "0"
|
||||||
|
defaultQuantization = "35"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RevidInst provides methods to control a revidInst session; providing methods
|
// RevidInst provides methods to control a revidInst session; providing methods
|
||||||
|
@ -149,31 +150,35 @@ type revidInst struct {
|
||||||
func NewRevidInstance(config Config) (r *revidInst, err error) {
|
func NewRevidInstance(config Config) (r *revidInst, err error) {
|
||||||
r = new(revidInst)
|
r = new(revidInst)
|
||||||
r.ringBuffer = ringbuffer.NewRingBuffer(bufferSize, mp2tPacketSize*mp2tMaxPackets)
|
r.ringBuffer = ringbuffer.NewRingBuffer(bufferSize, mp2tPacketSize*mp2tMaxPackets)
|
||||||
r.ChangeState(config)
|
err = r.ChangeState(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
switch r.config.Output {
|
switch r.config.Output {
|
||||||
case file:
|
case File:
|
||||||
r.outputFile, err = os.Create(r.config.OutputFileName)
|
r.outputFile, err = os.Create(r.config.OutputFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch r.config.Input {
|
switch r.config.Input {
|
||||||
case file:
|
case File:
|
||||||
r.inputFile, err = os.Open(r.config.InputFileName)
|
r.inputFile, err = os.Open(r.config.InputFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch r.config.InputCodec {
|
switch r.config.InputCodec {
|
||||||
case h264:
|
case H264:
|
||||||
|
r.Log(Info, "Using H264 parser!")
|
||||||
r.parser = parser.NewH264Parser()
|
r.parser = parser.NewH264Parser()
|
||||||
case mjpeg:
|
case Mjpeg:
|
||||||
r.parser = parser.NewMJPEGParser(mjpegParserInChanLen)
|
r.parser = parser.NewMJPEGParser(mjpegParserInChanLen)
|
||||||
}
|
}
|
||||||
switch r.config.Packetization {
|
switch r.config.Packetization {
|
||||||
case none:
|
case None:
|
||||||
r.parser.SetOutputChan(r.mjpegOutputChan)
|
r.parser.SetOutputChan(r.mjpegOutputChan)
|
||||||
case mpegts:
|
case Mpegts:
|
||||||
frameRateAsInt, _ := strconv.Atoi(r.config.FrameRate)
|
frameRateAsInt, _ := strconv.Atoi(r.config.FrameRate)
|
||||||
r.generator = tsgenerator.NewTsGenerator(uint(frameRateAsInt))
|
r.generator = tsgenerator.NewTsGenerator(uint(frameRateAsInt))
|
||||||
r.parser.SetOutputChan(r.generator.GetNalInputChan())
|
r.parser.SetOutputChan(r.generator.GetNalInputChan())
|
||||||
|
@ -219,46 +224,65 @@ func (r *revidInst) ChangeState(config Config) error {
|
||||||
switch config.Output {
|
switch config.Output {
|
||||||
case HttpOut:
|
case HttpOut:
|
||||||
case File:
|
case File:
|
||||||
case NothingDefine:
|
case NothingDefined:
|
||||||
r.Log(Warning, "No output defined, defaulting to httpOut!")
|
r.Log(Warning, "No output defined, defaulting to httpOut!")
|
||||||
config.Output = HttpOut
|
config.Output = HttpOut
|
||||||
default:
|
default:
|
||||||
return errors.New("Bad output type defined in config!")
|
return errors.New("Bad output type defined in config!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Width == "" {
|
||||||
|
r.Log(Warning, "No width defined, defaulting to 1280!")
|
||||||
|
config.Width = defaultWidth
|
||||||
|
} else {
|
||||||
if integer, err := strconv.Atoi(config.Width); integer < 0 || err != nil {
|
if integer, err := strconv.Atoi(config.Width); integer < 0 || err != nil {
|
||||||
return errors.New("Bad width defined in config!")
|
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 config.Height == "" {
|
||||||
|
r.Log(Warning, "No height defined, defaulting to 720!")
|
||||||
|
config.Height = defaultHeight
|
||||||
|
} else {
|
||||||
if integer, err := strconv.Atoi(config.Height); integer < 0 || err != nil {
|
if integer, err := strconv.Atoi(config.Height); integer < 0 || err != nil {
|
||||||
return errors.New("Bad height defined in config!")
|
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 config.FrameRate == "" {
|
||||||
}
|
r.Log(Warning, "No frame rate defined, defaulting to 25!")
|
||||||
if integer, _ := strconv.Atoi(config.FrameRate); integer == 0 {
|
|
||||||
r.Log(Warning, "No FrameRate defined, defaulting to 25!")
|
|
||||||
config.FrameRate = defaultFrameRate
|
config.FrameRate = defaultFrameRate
|
||||||
|
} else {
|
||||||
|
if integer, err := strconv.Atoi(config.FrameRate); integer < 0 || err != nil {
|
||||||
|
return errors.New("Bad frame rate defined in config!")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Timeout == "" {
|
||||||
|
r.Log(Warning, "No timeout defined, defaulting to 0!")
|
||||||
|
config.Timeout = defaultTimeout
|
||||||
|
} else {
|
||||||
if integer, err := strconv.Atoi(config.Timeout); integer < 0 || err != nil {
|
if integer, err := strconv.Atoi(config.Timeout); integer < 0 || err != nil {
|
||||||
return errors.New("Bad timeout defined 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!")
|
if config.IntraRefreshPeriod == "" {
|
||||||
|
r.Log(Warning, "No intra refresh defined, defaulting to 100!")
|
||||||
config.IntraRefreshPeriod = defaultIntraRefreshPeriod
|
config.IntraRefreshPeriod = defaultIntraRefreshPeriod
|
||||||
|
} else {
|
||||||
|
if integer, err := strconv.Atoi(config.IntraRefreshPeriod); integer < 0 || err != nil {
|
||||||
|
return errors.New("Bad intra refresh defined in config!")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Quantization == "" {
|
||||||
|
r.Log(Warning, "No quantization defined, defaulting to 35!")
|
||||||
|
config.Quantization = defaultQuantization
|
||||||
|
} else {
|
||||||
if integer, err := strconv.Atoi(config.Quantization); integer <= 0 || integer > 51 || err != nil {
|
if integer, err := strconv.Atoi(config.Quantization); integer <= 0 || integer > 51 || err != nil {
|
||||||
return errors.New("Bad quantization level defined in config!")
|
return errors.New("Bad quantization defined in config!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
r.config = config
|
r.config = config
|
||||||
return nil
|
return nil
|
||||||
|
@ -290,13 +314,13 @@ func (r *revidInst) Start() {
|
||||||
r.Log(Info, "Starting Revid!")
|
r.Log(Info, "Starting Revid!")
|
||||||
|
|
||||||
switch r.config.Input {
|
switch r.config.Input {
|
||||||
case raspivid:
|
case Raspivid:
|
||||||
r.Log(Info, "Starting raspivid!")
|
r.Log(Info, "Starting raspivid!")
|
||||||
var codec string
|
var codec string
|
||||||
switch r.config.InputCodec {
|
switch r.config.InputCodec {
|
||||||
case h264:
|
case H264:
|
||||||
codec = "H264"
|
codec = "H264"
|
||||||
case mjpeg:
|
case Mjpeg:
|
||||||
codec = "MJPEG"
|
codec = "MJPEG"
|
||||||
}
|
}
|
||||||
r.cmd = exec.Command("raspivid",
|
r.cmd = exec.Command("raspivid",
|
||||||
|
@ -320,7 +344,7 @@ func (r *revidInst) Start() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.isRunning = true
|
r.isRunning = true
|
||||||
case file:
|
case File:
|
||||||
stats, err := r.inputFile.Stat()
|
stats, err := r.inputFile.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Log(Error, "Could not get input file stats!")
|
r.Log(Error, "Could not get input file stats!")
|
||||||
|
@ -385,12 +409,12 @@ func (r *revidInst) packClips() {
|
||||||
if clip, err := r.ringBuffer.Get(); err != nil {
|
if clip, err := r.ringBuffer.Get(); err != nil {
|
||||||
r.Log(Error, err.Error())
|
r.Log(Error, err.Error())
|
||||||
switch r.config.Packetization {
|
switch r.config.Packetization {
|
||||||
case none:
|
case None:
|
||||||
r.Log(Warning, "Clearing mjpeg chan!")
|
r.Log(Warning, "Clearing mjpeg chan!")
|
||||||
for len(r.mjpegOutputChan) > 0 {
|
for len(r.mjpegOutputChan) > 0 {
|
||||||
<-(r.mjpegOutputChan)
|
<-(r.mjpegOutputChan)
|
||||||
}
|
}
|
||||||
case mpegts:
|
case Mpegts:
|
||||||
r.Log(Warning, "Clearing TS chan!")
|
r.Log(Warning, "Clearing TS chan!")
|
||||||
for len(r.generator.GetTsOutputChan()) > 0 {
|
for len(r.generator.GetTsOutputChan()) > 0 {
|
||||||
<-(r.generator.GetTsOutputChan())
|
<-(r.generator.GetTsOutputChan())
|
||||||
|
@ -400,13 +424,13 @@ func (r *revidInst) packClips() {
|
||||||
} else {
|
} else {
|
||||||
for {
|
for {
|
||||||
switch r.config.Packetization {
|
switch r.config.Packetization {
|
||||||
case none:
|
case None:
|
||||||
frame := <-r.mjpegOutputChan
|
frame := <-r.mjpegOutputChan
|
||||||
upperBound := clipSize + len(frame)
|
upperBound := clipSize + len(frame)
|
||||||
copy(clip[clipSize:upperBound], frame)
|
copy(clip[clipSize:upperBound], frame)
|
||||||
packetCount++
|
packetCount++
|
||||||
clipSize += len(frame)
|
clipSize += len(frame)
|
||||||
case mpegts:
|
case Mpegts:
|
||||||
tsPacket := <-(r.generator.GetTsOutputChan())
|
tsPacket := <-(r.generator.GetTsOutputChan())
|
||||||
tsByteSlice, err := tsPacket.ToByteSlice()
|
tsByteSlice, err := tsPacket.ToByteSlice()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -453,9 +477,9 @@ func (r *revidInst) outputClips() {
|
||||||
r.Log(Debug, fmt.Sprintf("Delay is: %v\n", delay))
|
r.Log(Debug, fmt.Sprintf("Delay is: %v\n", delay))
|
||||||
r.Log(Debug, fmt.Sprintf("Ring buffer size: %v\n", r.ringBuffer.GetNoOfElements()))
|
r.Log(Debug, fmt.Sprintf("Ring buffer size: %v\n", r.ringBuffer.GetNoOfElements()))
|
||||||
switch r.config.Output {
|
switch r.config.Output {
|
||||||
case file:
|
case File:
|
||||||
r.outputFile.Write(clip)
|
r.outputFile.Write(clip)
|
||||||
case httpOut:
|
case HttpOut:
|
||||||
bytes += len(clip)
|
bytes += len(clip)
|
||||||
for err := r.sendClipToHTTP(clip, r.config.HttpAddress); err != nil; {
|
for err := r.sendClipToHTTP(clip, r.config.HttpAddress); err != nil; {
|
||||||
r.Log(Error, err.Error())
|
r.Log(Error, err.Error())
|
||||||
|
|
|
@ -33,17 +33,19 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
// Test revidInst with a file input
|
// Test revidInst with a file input
|
||||||
func TestFileInput(t *testing.T){
|
func TestFileInput(t *testing.T){
|
||||||
config := Config{
|
config := Config{
|
||||||
Input: file,
|
Input: File,
|
||||||
InputFileName: "testInput.h264",
|
InputFileName: "testInput.h264",
|
||||||
Output: file,
|
Output: File,
|
||||||
OutputFileName: "output/TestFileAsInput.ts",
|
OutputFileName: "output/TestFileAsInput.ts",
|
||||||
}
|
}
|
||||||
revidInst, err := NewRevidInstance(config)
|
revidInst, err := NewRevidInstance(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Should not have got error!")
|
t.Errorf("Should not have got error!: %v\n", err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
revidInst.Start()
|
revidInst.Start()
|
||||||
time.Sleep(100*time.Second)
|
time.Sleep(100*time.Second)
|
||||||
|
@ -58,36 +60,37 @@ func TestRaspividH264Input(t *testing.T){
|
||||||
OutputFileName: "output/TestRaspividOutput.ts",
|
OutputFileName: "output/TestRaspividOutput.ts",
|
||||||
Width: "1280",
|
Width: "1280",
|
||||||
Height: "720",
|
Height: "720",
|
||||||
Bitrate: "1000000",
|
|
||||||
FrameRate: "25",
|
FrameRate: "25",
|
||||||
}
|
}
|
||||||
revidInst, err := NewRevidInstance(config)
|
revidInst, err := NewRevidInstance(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Should not have got an error!")
|
t.Errorf("Should not have got an error!")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
revidInst.Start()
|
revidInst.Start()
|
||||||
time.Sleep(100*time.Second)
|
time.Sleep(100*time.Second)
|
||||||
revidInst.Stop()
|
revidInst.Stop()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Test revidInst with a raspivid mjpeg input
|
// Test revidInst with a raspivid mjpeg input
|
||||||
func TestRaspividMJPEGInput(t *testing.T){
|
func TestRaspividMJPEGInput(t *testing.T){
|
||||||
config := Config{
|
config := Config{
|
||||||
Input: Raspivid,
|
Input: Raspivid,
|
||||||
InputCodec: mjpeg,
|
InputCodec: Mjpeg,
|
||||||
Output: File,
|
Output: File,
|
||||||
OutputFileName: "output/TestRaspividMjpegOutput.mjpeg",
|
OutputFileName: "output/TestRaspividMjpegOutput.mjpeg",
|
||||||
Width: "1280",
|
Width: "1280",
|
||||||
Height: "720",
|
Height: "720",
|
||||||
Bitrate: "0",
|
|
||||||
Quantization: "35",
|
Quantization: "35",
|
||||||
FrameRate: "25",
|
FrameRate: "25",
|
||||||
}
|
}
|
||||||
revidInst, err := NewRevidInstance(config)
|
revidInst, err := NewRevidInstance(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Should not of have got an error!")
|
t.Errorf("Should not of have got an error!")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
revidInst.Start()
|
revidInst.Start()
|
||||||
time.Sleep(100*time.Second)
|
time.Sleep(10*time.Second)
|
||||||
revidInst.Stop()
|
revidInst.Stop()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue