/* NAME Config.go DESCRIPTION See Readme.md AUTHORS Saxon A. Nelson-Milton LICENSE Config.go is Copyright (C) 2017-2018 the Australian Ocean Lab (AusOcean) It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with revid in gpl.txt. If not, see http://www.gnu.org/licenses. */ package revid import ( "errors" "bitbucket.org/ausocean/utils/logger" ) // Config provides parameters relevant to a revid instance. A new config must // be passed to the constructor. type Config struct { LogLevel int8 Input uint8 InputCodec uint8 Outputs []uint8 RtmpMethod uint8 Packetization uint8 // Quantize specifies whether the input to // revid will have constant or variable // bitrate. Quantize bool FramesPerClip uint RtmpUrl string Bitrate uint OutputPath string InputPath string Height uint Width uint FrameRate uint HttpAddress string Quantization uint IntraRefreshPeriod uint RtpAddress string Logger Logger SendRetry bool BurstPeriod uint Rotate uint } // Enums for config struct const ( NothingDefined = iota Raspivid V4L H264Codec File Http H264 Mjpeg None Mpegts Ffmpeg Flv LibRtmp QuantizationOn QuantizationOff Yes No Rtmp FfmpegRtmp Udp MpegtsRtp Rtp ) // Default config settings const ( defaultInput = Raspivid defaultOutput = Http defaultPacketization = Flv defaultFrameRate = 25 defaultWidth = 1280 defaultHeight = 720 defaultIntraRefreshPeriod = 100 defaultTimeout = 0 defaultQuantization = 40 defaultBitrate = 400000 defaultQuantizationMode = QuantizationOff defaultFramesPerClip = 1 httpFramesPerClip = 560 defaultInputCodec = H264 defaultVerbosity = No // FIXME(kortschak): This makes no sense whatsoever. No is currently 15. defaultRtpAddr = "localhost:6970" defaultBurstPeriod = 10 // Seconds defaultRotate = 0 // Degrees ) // Validate checks for any errors in the config fields and defaults settings // if particular parameters have not been defined. func (c *Config) Validate(r *Revid) error { switch c.LogLevel { case Yes: case No: case NothingDefined: c.LogLevel = defaultVerbosity c.Logger.Log(logger.Warning, pkg+"no LogLevel mode defined, defaulting", "LogLevel", defaultVerbosity) default: return errors.New("bad LogLevel defined in config") } switch c.Input { case Raspivid, V4L, File: case NothingDefined: c.Logger.Log(logger.Warning, pkg+"no input type defined, defaulting", "input", defaultInput) c.Input = defaultInput default: return errors.New("bad input type defined in config") } switch c.InputCodec { case H264: // FIXME(kortschak): This is not really what we want. // Configuration really needs to be rethought here. if c.Quantize && c.Quantization == 0 { c.Quantization = defaultQuantization } if (c.Bitrate > 0 && c.Quantize) || (c.Bitrate == 0 && !c.Quantize) { return errors.New("bad bitrate and quantization combination for H264 input") } case Mjpeg: if c.Quantization > 0 || c.Bitrate == 0 { return errors.New("bad bitrate or quantization for mjpeg input") } case NothingDefined: c.Logger.Log(logger.Warning, pkg+"no input codec defined, defaulting", "inputCodec", defaultInputCodec) c.InputCodec = defaultInputCodec c.Logger.Log(logger.Warning, pkg+"defaulting quantization", "quantization", defaultQuantization) c.Quantization = defaultQuantization default: return errors.New("bad input codec defined in config") } for i, o := range c.Outputs { switch o { case File: case Udp: case Rtmp, FfmpegRtmp: if c.RtmpUrl == "" { c.Logger.Log(logger.Info, pkg+"no RTMP URL: falling back to HTTP") c.Outputs[i] = Http // FIXME(kortschak): Does this want the same line as below? // c.FramesPerClip = httpFramesPerClip break } c.Logger.Log(logger.Info, pkg+"defaulting frames per clip for rtmp out", "framesPerClip", defaultFramesPerClip) c.FramesPerClip = defaultFramesPerClip c.Packetization = Flv c.SendRetry = true case NothingDefined: c.Logger.Log(logger.Warning, pkg+"no output defined, defaulting", "output", defaultOutput) c.Outputs[i] = defaultOutput c.Packetization = defaultPacketization fallthrough case Http, Rtp: c.Logger.Log(logger.Info, pkg+"defaulting frames per clip for http out", "framesPerClip", httpFramesPerClip) c.FramesPerClip = httpFramesPerClip c.Packetization = Mpegts default: return errors.New("bad output type defined in config") } } if c.BurstPeriod == 0 { c.Logger.Log(logger.Warning, pkg+"no burst period defined, defaulting", "burstPeriod", defaultBurstPeriod) c.BurstPeriod = defaultBurstPeriod } if c.FramesPerClip < 1 { c.Logger.Log(logger.Warning, pkg+"no FramesPerClip defined, defaulting", "framesPerClip", defaultFramesPerClip) c.FramesPerClip = defaultFramesPerClip } if c.Rotate > 359 { c.Logger.Log(logger.Warning, pkg+"bad rotate angle, defaulting", "angle", defaultRotate) c.Rotate = defaultRotate } if c.Width == 0 { c.Logger.Log(logger.Warning, pkg+"no width defined, defaulting", "width", defaultWidth) c.Width = defaultWidth } if c.Height == 0 { c.Logger.Log(logger.Warning, pkg+"no height defined, defaulting", "height", defaultHeight) c.Height = defaultHeight } if c.FrameRate == 0 { c.Logger.Log(logger.Warning, pkg+"no frame rate defined, defaulting", "fps", defaultFrameRate) c.FrameRate = defaultFrameRate } if c.Bitrate == 0 { c.Logger.Log(logger.Warning, pkg+"no bitrate defined, defaulting", "bitrate", defaultBitrate) c.Bitrate = defaultBitrate } if c.IntraRefreshPeriod == 0 { c.Logger.Log(logger.Warning, pkg+"no intra refresh defined, defaulting", "intraRefresh", defaultIntraRefreshPeriod) c.IntraRefreshPeriod = defaultIntraRefreshPeriod } if c.Quantization == 0 { c.Logger.Log(logger.Warning, pkg+"no quantization defined, defaulting", "quantization", defaultQuantization) c.Quantization = defaultQuantization } else if c.Quantization > 51 { return errors.New("quantisation is over threshold") } if c.RtpAddress == "" { c.RtpAddress = defaultRtpAddr } return nil }