mirror of https://bitbucket.org/ausocean/av.git
increasing robustness
This commit is contained in:
parent
8cd62fc0d6
commit
d39c6483eb
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bitbucket.org/ausocean/av/revid"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Give the platform some time to set itself up
|
||||
time.Sleep(30 * time.Second)
|
||||
config := revid.Config{
|
||||
Input: revid.Raspivid,
|
||||
Output: revid.Rtmp,
|
||||
RtmpMethod: revid.LibRtmp,
|
||||
QuantizationMode: revid.QuantizationOff,
|
||||
RtmpUrl: "rtmp://a.rtmp.youtube.com/live2/w44c-mkuu-aezg-ceb1",
|
||||
Bitrate: "500000",
|
||||
Packetization: revid.Flv,
|
||||
}
|
||||
revidInst, err := revid.NewRevidInstance(config)
|
||||
if err != nil {
|
||||
fmt.Println("Should not have got error!")
|
||||
return
|
||||
}
|
||||
// Run this instance for 2 days! Power to the pi will surely turn itself
|
||||
// off before this time is up.
|
||||
revidInst.Start()
|
||||
time.Sleep(2 * 43200 * time.Second)
|
||||
revidInst.Stop()
|
||||
}
|
|
@ -45,6 +45,7 @@ type Config struct {
|
|||
RtmpMethod uint8
|
||||
Packetization uint8
|
||||
QuantizationMode uint8
|
||||
Verbosity uint8
|
||||
FramesPerClip int
|
||||
RtmpUrl string
|
||||
Bitrate string
|
||||
|
@ -79,6 +80,8 @@ const (
|
|||
LibRtmp = 14
|
||||
QuantizationOn = 15
|
||||
QuantizationOff = 16
|
||||
Yes = 17
|
||||
No = 18
|
||||
)
|
||||
|
||||
// Default config settings
|
||||
|
@ -91,11 +94,22 @@ const (
|
|||
defaultQuantization = "40"
|
||||
defaultBitrate = "0"
|
||||
defaultQuantizationMode = QuantizationOff
|
||||
defaultFramesPerClip = 1
|
||||
)
|
||||
|
||||
// Validate checks for any errors in the config files and defaults settings
|
||||
// Validate checks for any errors in the config fields and defaults settings
|
||||
// if particular parameters have not been defined.
|
||||
func (config *Config) Validate(r *revidInst) error {
|
||||
switch config.Verbosity {
|
||||
case Yes:
|
||||
case No:
|
||||
case NothingDefined:
|
||||
config.Verbosity = No
|
||||
r.Log(Warning, "No verbosity mode defined, defaulting to no Verbosity!")
|
||||
default:
|
||||
return errors.New("Bad Verbosity defined in config!")
|
||||
}
|
||||
|
||||
switch config.QuantizationMode {
|
||||
case QuantizationOn:
|
||||
case QuantizationOff:
|
||||
|
@ -103,7 +117,7 @@ func (config *Config) Validate(r *revidInst) error {
|
|||
r.Log(Warning, "No quantization mode defined, defaulting to QuantizationOff!")
|
||||
config.QuantizationMode = QuantizationOff
|
||||
default:
|
||||
return errors.New("Bad QuantizationMode define in config!")
|
||||
return errors.New("Bad QuantizationMode defined in config!")
|
||||
}
|
||||
|
||||
switch config.Input {
|
||||
|
@ -120,15 +134,24 @@ func (config *Config) Validate(r *revidInst) error {
|
|||
switch config.InputCodec {
|
||||
case H264:
|
||||
if config.Bitrate != "" && config.Quantization != "" {
|
||||
bitrate, _ := strconv.Atoi(config.Bitrate)
|
||||
quantization, _ := strconv.Atoi(config.Quantization)
|
||||
bitrate, err := strconv.Atoi(config.Bitrate)
|
||||
if err != nil {
|
||||
return errors.New("Something is wrong with bitrate in conig!")
|
||||
}
|
||||
quantization, err := strconv.Atoi(config.Quantization)
|
||||
if err != nil {
|
||||
return errors.New("Something is wrong with quantization in config!")
|
||||
}
|
||||
if (bitrate > 0 && quantization > 0) || (bitrate == 0 && quantization == 0) {
|
||||
return errors.New("Bad bitrate and quantization combination for H264 input!")
|
||||
}
|
||||
}
|
||||
case Mjpeg:
|
||||
if config.Quantization != "" {
|
||||
quantization, _ := strconv.Atoi(config.Quantization)
|
||||
quantization, err := strconv.Atoi(config.Quantization)
|
||||
if err != nil {
|
||||
return errors.New("Something is wrong with quantization in config!")
|
||||
}
|
||||
if quantization > 0 || config.Bitrate == "" {
|
||||
return errors.New("Bad bitrate or quantization for mjpeg input!")
|
||||
}
|
||||
|
@ -150,6 +173,8 @@ func (config *Config) Validate(r *revidInst) error {
|
|||
if config.RtmpUrl == "" {
|
||||
return errors.New("Bad RTMP URL")
|
||||
}
|
||||
r.Log(Info, "Defaulting frames per clip to 1 for rtmp output!")
|
||||
config.FramesPerClip = 1
|
||||
case NothingDefined:
|
||||
r.Log(Warning, "No output defined, defaulting to httpOut!")
|
||||
config.Output = Http
|
||||
|
@ -182,7 +207,7 @@ func (config *Config) Validate(r *revidInst) error {
|
|||
case config.FramesPerClip > 0:
|
||||
case config.FramesPerClip == 0:
|
||||
r.Log(Warning, "No frames per clip defined, defaulting to 1!")
|
||||
config.FramesPerClip = 1
|
||||
config.FramesPerClip = defaultFramesPerClip
|
||||
case config.FramesPerClip < 0:
|
||||
return errors.New("Bad frames per clip given!")
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import (
|
|||
"os/exec"
|
||||
"strconv"
|
||||
"time"
|
||||
"sync"
|
||||
|
||||
"bitbucket.org/ausocean/av/generator"
|
||||
"bitbucket.org/ausocean/av/parser"
|
||||
|
@ -84,7 +85,7 @@ const (
|
|||
type RevidInst interface {
|
||||
Start()
|
||||
Stop()
|
||||
ChangeState(newconfig Config) error
|
||||
changeState(newconfig Config) error
|
||||
GetConfigRef() *Config
|
||||
Log(logType, m string)
|
||||
IsRunning() bool
|
||||
|
@ -111,6 +112,7 @@ type revidInst struct {
|
|||
getFrame func() []byte
|
||||
sendClip func(clip []byte) error
|
||||
rtmpInst rtmp.RTMPSession
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// NewRevidInstance returns a pointer to a new revidInst with the desired
|
||||
|
@ -118,10 +120,12 @@ type revidInst struct {
|
|||
// successful.
|
||||
func NewRevidInstance(config Config) (r *revidInst, err error) {
|
||||
r = new(revidInst)
|
||||
r.mutex = sync.Mutex{}
|
||||
r.ringBuffer = ringbuffer.NewRingBuffer(ringBufferSize, ringBufferElementSize)
|
||||
err = r.ChangeState(config)
|
||||
err = r.changeState(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
r = nil
|
||||
return
|
||||
}
|
||||
r.outputChan = make(chan []byte, outputChanSize)
|
||||
r.parser.Start()
|
||||
|
@ -136,9 +140,9 @@ func (r *revidInst) GetConfigRef() *Config {
|
|||
return &r.config
|
||||
}
|
||||
|
||||
// ChangeState swaps the current config of a revidInst with the passed
|
||||
// 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 {
|
||||
func (r *revidInst) changeState(config Config) error {
|
||||
r.config.Logger = config.Logger
|
||||
err := config.Validate(r)
|
||||
if err != nil {
|
||||
|
@ -204,6 +208,17 @@ noPacketizationSetup:
|
|||
return nil
|
||||
}
|
||||
|
||||
// ChangeConfig changes the current configuration of the revid instance.
|
||||
func (r *revidInst) ChangeConfig(config Config) (err error) {
|
||||
r.Stop()
|
||||
r, err = NewRevidInstance(config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r.Start()
|
||||
return
|
||||
}
|
||||
|
||||
// Log takes a logtype and message and tries to send this information to the
|
||||
// logger provided in the revidInst config - if there is one, otherwise the message
|
||||
// is sent to stdout
|
||||
|
@ -211,7 +226,9 @@ func (r *revidInst) Log(logType, m string) {
|
|||
if r.config.Logger != nil {
|
||||
r.config.Logger.Log(logType, m)
|
||||
} else {
|
||||
// fmt.Println(logType + ": " + m)
|
||||
if r.config.Verbosity == Yes {
|
||||
fmt.Println(logType + ": " + m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,6 +240,8 @@ func (r *revidInst) IsRunning() bool {
|
|||
// Start invokes a revidInst to start processing video from a defined input
|
||||
// and packetising (if theres packetization) to a defined output.
|
||||
func (r *revidInst) Start() {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
if r.isRunning {
|
||||
r.Log(Warning, "revidInst.Start() called but revid already running!")
|
||||
return
|
||||
|
@ -242,16 +261,18 @@ func (r *revidInst) Start() {
|
|||
|
||||
// Stop halts any processing of video data from a camera or file
|
||||
func (r *revidInst) Stop() {
|
||||
if r.isRunning {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
if !r.isRunning {
|
||||
r.Log(Warning, "revidInst.Stop() called but revid not running!")
|
||||
return
|
||||
}
|
||||
r.Log(Info, "Stopping revid!")
|
||||
r.isRunning = false
|
||||
// If a cmd process is running, we kill!
|
||||
if r.cmd != nil && r.cmd.Process != nil {
|
||||
r.cmd.Process.Kill()
|
||||
}
|
||||
} else {
|
||||
r.Log(Warning, "revidInst.Stop() called but revid not running!")
|
||||
}
|
||||
}
|
||||
|
||||
// getFrameNoPacketization gets a frame directly from the revid output chan
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
"fmt"
|
||||
"bitbucket.org/ausocean/av/revid"
|
||||
)
|
||||
|
||||
func main(){
|
||||
time.Sleep(30*time.Second)
|
||||
config := revid.Config{
|
||||
Input: revid.Raspivid,
|
||||
Output: revid.Rtmp,
|
||||
RtmpMethod: revid.LibRtmp,
|
||||
QuantizationMode: revid.QuantizationOff,
|
||||
RtmpUrl: "rtmp://a.rtmp.youtube.com/live2/w44c-mkuu-aezg-ceb1",
|
||||
Bitrate: "500000",
|
||||
FramesPerClip: 1,
|
||||
Packetization: revid.Flv,
|
||||
FrameRate: "25",
|
||||
}
|
||||
revidInst, err := revid.NewRevidInstance(config)
|
||||
if err != nil {
|
||||
fmt.Println("Should not have got error!")
|
||||
return
|
||||
}
|
||||
revidInst.Start()
|
||||
time.Sleep(2*43200*time.Second)
|
||||
revidInst.Stop()
|
||||
}
|
Loading…
Reference in New Issue