diff --git a/revid/config.go b/revid/config.go index 066ce9f6..447ba0c2 100644 --- a/revid/config.go +++ b/revid/config.go @@ -58,7 +58,7 @@ type Config struct { Quantization string Timeout string IntraRefreshPeriod string - Logger smartlogger.LogInstance + Logger Logger } // Enums for config struct @@ -109,7 +109,7 @@ func (c *Config) Validate(r *Revid) error { case No: case NothingDefined: c.Verbosity = Yes - r.Log(Warning, "No verbosity mode defined, defaulting to no Verbosity!") + c.Logger.Log(smartlogger.Warning, "No verbosity mode defined, defaulting to no Verbosity!") default: return errors.New("Bad Verbosity defined in config!") } @@ -118,7 +118,7 @@ func (c *Config) Validate(r *Revid) error { case QuantizationOn: case QuantizationOff: case NothingDefined: - r.Log(Warning, "No quantization mode defined, defaulting to QuantizationOff!") + c.Logger.Log(smartlogger.Warning, "No quantization mode defined, defaulting to QuantizationOff!") c.QuantizationMode = QuantizationOff default: return errors.New("Bad QuantizationMode defined in config!") @@ -128,7 +128,7 @@ func (c *Config) Validate(r *Revid) error { case Raspivid: case File: case NothingDefined: - r.Log(Warning, "No input type defined, defaulting to raspivid!") + c.Logger.Log(smartlogger.Warning, "No input type defined, defaulting to raspivid!") c.Input = defaultInput default: return errors.New("Bad input type defined in config!") @@ -160,9 +160,9 @@ func (c *Config) Validate(r *Revid) error { } } case NothingDefined: - r.Log(Warning, "No input codec defined, defaulting to h264!") + c.Logger.Log(smartlogger.Warning, "No input codec defined, defaulting to h264!") c.InputCodec = H264 - r.Log(Warning, "Defaulting bitrate to 0 and quantization to 35!") + c.Logger.Log(smartlogger.Warning, "Defaulting bitrate to 0 and quantization to 35!") c.Quantization = defaultQuantization default: return errors.New("Bad input codec defined in config!") @@ -172,18 +172,18 @@ func (c *Config) Validate(r *Revid) error { case File: case Rtmp, FfmpegRtmp: if c.RtmpUrl == "" { - r.Log(Info, "No RTMP URL: falling back to HTTP") + c.Logger.Log(smartlogger.Info, "No RTMP URL: falling back to HTTP") c.Output = Http break } - r.Log(Info, "Defaulting frames per clip to 1 for rtmp output!") + c.Logger.Log(smartlogger.Info, "Defaulting frames per clip to 1 for rtmp output!") c.FramesPerClip = 1 case NothingDefined: - r.Log(Warning, "No output defined, defaulting to httpOut!") + c.Logger.Log(smartlogger.Warning, "No output defined, defaulting to httpOut!") c.Output = defaultOutput fallthrough case Http: - r.Log(Info, "Defaulting frames per clip to 7 for http output!") + c.Logger.Log(smartlogger.Info, "Defaulting frames per clip to 7 for http output!") c.FramesPerClip = 7 default: return errors.New("Bad output type defined in config!") @@ -194,7 +194,7 @@ func (c *Config) Validate(r *Revid) error { case Mpegts: case Flv: case NothingDefined: - r.Log(Warning, "No packetization option defined, defaulting to none!") + c.Logger.Log(smartlogger.Warning, "No packetization option defined, defaulting to none!") c.Packetization = Flv default: return errors.New("Bad packetization option defined in config!") @@ -204,7 +204,7 @@ func (c *Config) Validate(r *Revid) error { case Yes: case No: case NothingDefined: - r.Log(Warning, "No horizontal flip option defined, defaulting to not flipped!") + c.Logger.Log(smartlogger.Warning, "No horizontal flip option defined, defaulting to not flipped!") c.HorizontalFlip = defaultHorizontalFlip default: return errors.New("Bad horizontal flip option defined in config!") @@ -214,19 +214,19 @@ func (c *Config) Validate(r *Revid) error { case Yes: case No: case NothingDefined: - r.Log(Warning, "No vertical flip option defined, defaulting to not flipped!") + c.Logger.Log(smartlogger.Warning, "No vertical flip option defined, defaulting to not flipped!") c.VerticalFlip = defaultVerticalFlip default: return errors.New("Bad vertical flip option defined in config!") } if c.FramesPerClip < 1 { - r.Log(Warning, "No FramesPerClip defined defined, defaulting to 1!") + c.Logger.Log(smartlogger.Warning, "No FramesPerClip defined defined, defaulting to 1!") c.FramesPerClip = defaultFramesPerClip } if c.Width == "" { - r.Log(Warning, "No width defined, defaulting to 1280!") + c.Logger.Log(smartlogger.Warning, "No width defined, defaulting to 1280!") c.Width = defaultWidth } else { if integer, err := strconv.Atoi(c.Width); integer < 0 || err != nil { @@ -235,7 +235,7 @@ func (c *Config) Validate(r *Revid) error { } if c.Height == "" { - r.Log(Warning, "No height defined, defaulting to 720!") + c.Logger.Log(smartlogger.Warning, "No height defined, defaulting to 720!") c.Height = defaultHeight } else { if integer, err := strconv.Atoi(c.Height); integer < 0 || err != nil { @@ -244,7 +244,7 @@ func (c *Config) Validate(r *Revid) error { } if c.FrameRate == "" { - r.Log(Warning, "No frame rate defined, defaulting to 25!") + c.Logger.Log(smartlogger.Warning, "No frame rate defined, defaulting to 25!") c.FrameRate = defaultFrameRate } else { if integer, err := strconv.Atoi(c.FrameRate); integer < 0 || err != nil { @@ -253,7 +253,7 @@ func (c *Config) Validate(r *Revid) error { } if c.Bitrate == "" { - r.Log(Warning, "No bitrate defined, defaulting!") + c.Logger.Log(smartlogger.Warning, "No bitrate defined, defaulting!") c.Bitrate = defaultBitrate } else { if integer, err := strconv.Atoi(c.Bitrate); integer < 0 || err != nil { @@ -262,7 +262,7 @@ func (c *Config) Validate(r *Revid) error { } if c.Timeout == "" { - r.Log(Warning, "No timeout defined, defaulting to 0!") + c.Logger.Log(smartlogger.Warning, "No timeout defined, defaulting to 0!") c.Timeout = defaultTimeout } else { if integer, err := strconv.Atoi(c.Timeout); integer < 0 || err != nil { @@ -271,7 +271,7 @@ func (c *Config) Validate(r *Revid) error { } if c.IntraRefreshPeriod == "" { - r.Log(Warning, "No intra refresh defined, defaulting to 100!") + c.Logger.Log(smartlogger.Warning, "No intra refresh defined, defaulting to 100!") c.IntraRefreshPeriod = defaultIntraRefreshPeriod } else { if integer, err := strconv.Atoi(c.IntraRefreshPeriod); integer < 0 || err != nil { @@ -280,7 +280,7 @@ func (c *Config) Validate(r *Revid) error { } if c.Quantization == "" { - r.Log(Warning, "No quantization defined, defaulting to 35!") + c.Logger.Log(smartlogger.Warning, "No quantization defined, defaulting to 35!") c.Quantization = defaultQuantization } else { if integer, err := strconv.Atoi(c.Quantization); integer < 0 || integer > 51 || err != nil { diff --git a/revid/revid.go b/revid/revid.go index 69361999..600483d8 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -45,6 +45,7 @@ import ( "bitbucket.org/ausocean/av/stream/mts" "bitbucket.org/ausocean/iot/pi/netsender" "bitbucket.org/ausocean/utils/ring" + "bitbucket.org/ausocean/utils/smartlogger" ) // Misc constants @@ -82,6 +83,11 @@ const ( Detail = "Detail" ) +type Logger interface { + SetLevel(int8) + Log(level int8, message string, params ...interface{}) +} + // Revid provides methods to control a revid session; providing methods // to start, stop and change the state of an instance using the Config struct. type Revid struct { @@ -146,7 +152,7 @@ func (r *Revid) reset(config Config) error { if r.destination != nil { err = r.destination.close() if err != nil { - r.Log(Error, err.Error()) + r.config.Logger.Log(smartlogger.Error, err.Error()) } } switch r.config.Output { @@ -163,13 +169,13 @@ func (r *Revid) reset(config Config) error { } r.destination = s case Rtmp: - s, err := newRtmpSender(config.RtmpUrl, rtmpConnectionTimout, rtmpConnectionMaxTries, r.Log) + s, err := newRtmpSender(config.RtmpUrl, rtmpConnectionTimout, rtmpConnectionMaxTries, r.config.Logger.Log) if err != nil { return err } r.destination = s case Http: - r.destination = newHttpSender(r.ns, r.Log) + r.destination = newHttpSender(r.ns, r.config.Logger.Log) } switch r.config.Input { @@ -180,10 +186,10 @@ func (r *Revid) reset(config Config) error { } switch r.config.InputCodec { case H264: - r.Log(Info, "using H264 lexer") + r.config.Logger.Log(smartlogger.Info, "using H264 lexer") r.lexTo = lex.H264 case Mjpeg: - r.Log(Info, "using MJPEG lexer") + r.config.Logger.Log(smartlogger.Info, "using MJPEG lexer") r.lexTo = lex.MJPEG } @@ -209,11 +215,11 @@ func (r *Revid) reset(config Config) error { r.getFrame = r.getFrameNoPacketization return nil case Mpegts: - r.Log(Info, "Using MPEGTS packetisation") + r.config.Logger.Log(smartlogger.Info, "Using MPEGTS packetisation") frameRate, _ := strconv.ParseFloat(r.config.FrameRate, 64) r.encoder = mts.NewEncoder(frameRate) case Flv: - r.Log(Info, "Using FLV packetisation") + r.config.Logger.Log(smartlogger.Info, "Using FLV packetisation") frameRate, _ := strconv.Atoi(r.config.FrameRate) r.encoder = flv.NewEncoder(true, true, frameRate) } @@ -224,20 +230,6 @@ func (r *Revid) reset(config Config) error { return nil } -// Log takes a logtype and message and tries to send this information to the -// logger provided in the revid config - if there is one, otherwise the message -// is sent to stdout -func (r *Revid) Log(logType, m string) { - if r.config.Verbosity != Yes { - return - } - if r.config.Logger != nil { - r.config.Logger.Log("revid", logType, m) - return - } - fmt.Println(logType + ": " + m) -} - // IsRunning returns whether the receiver is running. func (r *Revid) IsRunning() bool { return r.isRunning @@ -247,31 +239,31 @@ func (r *Revid) IsRunning() bool { // and packetising (if theres packetization) to a defined output. func (r *Revid) Start() { if r.isRunning { - r.Log(Warning, "Revid.Start() called but revid already running!") + r.config.Logger.Log(smartlogger.Warning, "Revid.Start() called but revid already running!") return } - r.Log(Info, "Starting Revid") - r.Log(Debug, "Setting up output") + r.config.Logger.Log(smartlogger.Info, "Starting Revid") + r.config.Logger.Log(smartlogger.Debug, "Setting up output") r.isRunning = true - r.Log(Info, "Starting output routine") + r.config.Logger.Log(smartlogger.Info, "Starting output routine") go r.outputClips() - r.Log(Info, "Starting clip packing routine") + r.config.Logger.Log(smartlogger.Info, "Starting clip packing routine") go r.packClips() - r.Log(Info, "Setting up input and receiving content") + r.config.Logger.Log(smartlogger.Info, "Setting up input and receiving content") go r.setupInput() } // Stop halts any processing of video data from a camera or file func (r *Revid) Stop() { if !r.isRunning { - r.Log(Warning, "Revid.Stop() called but revid not running!") + r.config.Logger.Log(smartlogger.Warning, "Revid.Stop() called but revid not running!") return } - r.Log(Info, "Stopping revid!") + r.config.Logger.Log(smartlogger.Info, "Stopping revid!") r.isRunning = false - r.Log(Info, "Killing input proccess!") + r.config.Logger.Log(smartlogger.Info, "Killing input proccess!") // If a cmd process is running, we kill! if r.cmd != nil && r.cmd.Process != nil { r.cmd.Process.Kill() @@ -305,16 +297,16 @@ func (r *Revid) packClips() { case frame := <-r.encoder.Stream(): lenOfFrame := len(frame) if lenOfFrame > ringBufferElementSize { - r.Log(Warning, fmt.Sprintf("Frame was too big: %v bytes, getting another one!", lenOfFrame)) + r.config.Logger.Log(smartlogger.Warning, fmt.Sprintf("Frame was too big: %v bytes, getting another one!", lenOfFrame)) frame = r.getFrame() lenOfFrame = len(frame) } _, err := r.ringBuffer.Write(frame) if err != nil { if err == ring.ErrDropped { - r.Log(Warning, fmt.Sprintf("dropped %d byte frame", len(frame))) + r.config.Logger.Log(smartlogger.Warning, fmt.Sprintf("dropped %d byte frame", len(frame))) } else { - r.Log(Error, err.Error()) + r.config.Logger.Log(smartlogger.Error, err.Error()) } } packetCount++ @@ -357,51 +349,51 @@ func (r *Revid) outputClips() { } bytes += chunk.Len() - r.Log(Detail, "About to send") + r.config.Logger.Log(smartlogger.Debug, "About to send") err = r.destination.load(chunk) if err != nil { - r.Log(Error, "failed to load clip") + r.config.Logger.Log(smartlogger.Error, "failed to load clip") } err = r.destination.send() if err == nil { - r.Log(Detail, "sent clip") + r.config.Logger.Log(smartlogger.Debug, "sent clip") } if r.isRunning && err != nil && chunk.Len() > 11 { - r.Log(Debug, "Send failed! Trying again") + r.config.Logger.Log(smartlogger.Debug, "Send failed! Trying again") // Try and send again err = r.destination.send() - r.Log(Error, err.Error()) + r.config.Logger.Log(smartlogger.Error, err.Error()) // if there's still an error we try and reconnect, unless we're stopping for r.isRunning && err != nil { - r.Log(Debug, "Send failed a again! Trying to reconnect...") + r.config.Logger.Log(smartlogger.Debug, "Send failed a again! Trying to reconnect...") time.Sleep(time.Duration(sendFailedDelay) * time.Millisecond) - r.Log(Error, err.Error()) + r.config.Logger.Log(smartlogger.Error, err.Error()) if rs, ok := r.destination.(restarter); ok { - r.Log(Debug, fmt.Sprintf("restarting %T session", rs)) + r.config.Logger.Log(smartlogger.Debug, fmt.Sprintf("restarting %T session", rs)) err = rs.restart() if err != nil { // TODO(kortschak): Make this "Fatal" when that exists. - r.Log(Error, "failed to restart rtmp session") + r.config.Logger.Log(smartlogger.Error, "failed to restart rtmp session") r.isRunning = false return } - r.Log(Info, "restarted rtmp session") + r.config.Logger.Log(smartlogger.Info, "restarted rtmp session") } - r.Log(Debug, "Trying to send again with new connection...") + r.config.Logger.Log(smartlogger.Debug, "Trying to send again with new connection...") err = r.destination.send() if err != nil { - r.Log(Error, err.Error()) + r.config.Logger.Log(smartlogger.Error, err.Error()) } } } r.destination.release() - r.Log(Detail, "Done reading that clip from ringbuffer...") + r.config.Logger.Log(smartlogger.Debug, "Done reading that clip from ringbuffer...") // Log some information regarding bitrate and ring buffer size if it's time now = time.Now() @@ -409,23 +401,23 @@ func (r *Revid) outputClips() { if deltaTime > bitrateTime { // FIXME(kortschak): For subsecond deltaTime, this will give infinite bitrate. r.bitrate = int(float64(bytes*8) / float64(deltaTime/time.Second)) - r.Log(Debug, fmt.Sprintf("Bitrate: %v bits/s\n", r.bitrate)) - r.Log(Debug, fmt.Sprintf("Ring buffer size: %v\n", r.ringBuffer.Len())) + r.config.Logger.Log(smartlogger.Debug, fmt.Sprintf("Bitrate: %v bits/s\n", r.bitrate)) + r.config.Logger.Log(smartlogger.Debug, fmt.Sprintf("Ring buffer size: %v\n", r.ringBuffer.Len())) prevTime = now bytes = 0 } } - r.Log(Info, "Not outputting clips anymore!") + r.config.Logger.Log(smartlogger.Info, "Not outputting clips anymore!") err := r.destination.close() if err != nil { - r.Log(Error, "failed to close destination") + r.config.Logger.Log(smartlogger.Error, "failed to close destination") } } // startRaspivid sets up things for input from raspivid i.e. starts // a raspivid process and pipes it's data output. func (r *Revid) startRaspivid() error { - r.Log(Info, "Starting raspivid!") + r.config.Logger.Log(smartlogger.Info, "Starting raspivid!") switch r.config.InputCodec { case H264: args := []string{ @@ -450,7 +442,7 @@ func (r *Revid) startRaspivid() error { args = append(args, "-vf") } - r.Log(Info, fmt.Sprintf("Starting raspivid with args: %v", args)) + r.config.Logger.Log(smartlogger.Info, fmt.Sprintf("Starting raspivid with args: %v", args)) r.cmd = exec.Command("raspivid", args...) case Mjpeg: @@ -472,9 +464,9 @@ func (r *Revid) startRaspivid() error { } r.inputReader = stdout go func() { - r.Log(Info, "Reading camera data!") + r.config.Logger.Log(smartlogger.Info, "Reading camera data!") r.lexTo(r.encoder, r.inputReader, 0) - r.Log(Info, "Not trying to read from camera anymore!") + r.config.Logger.Log(smartlogger.Info, "Not trying to read from camera anymore!") }() return nil } @@ -489,7 +481,7 @@ func (r *Revid) setupInputForFile() error { f, err := os.Open(r.config.InputFileName) if err != nil { - r.Log(Error, err.Error()) + r.config.Logger.Log(smartlogger.Error, err.Error()) r.Stop() return err }