/* 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" "strconv" "bitbucket.org/ausocean/utils/smartlogger" ) // 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 RtmpMethod uint8 Packetization uint8 QuantizationMode uint8 Verbosity int8 HorizontalFlip uint8 VerticalFlip uint8 FramesPerClip int RtmpUrl string Bitrate string OutputFileName string InputFileName string Height string Width string FrameRate string HttpAddress string Quantization string Timeout string IntraRefreshPeriod string Logger Logger } // Enums for config struct const ( NothingDefined = iota Raspivid H264Codec File Http H264 Mjpeg None Mpegts Ffmpeg Flv LibRtmp QuantizationOn QuantizationOff Yes No Rtmp FfmpegRtmp ) // Default config settings const ( defaultInput = Raspivid defaultOutput = Http defaultPacketization = Flv defaultFrameRate = "25" defaultWidth = "1280" defaultHeight = "720" defaultIntraRefreshPeriod = "100" defaultTimeout = "0" defaultQuantization = "40" defaultBitrate = "500000" defaultQuantizationMode = QuantizationOff defaultFramesPerClip = 1 defaultVerticalFlip = No defaultHorizontalFlip = No ) // 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.Verbosity { case Yes: case No: case NothingDefined: c.Verbosity = Yes c.Logger.Log(smartlogger.Warning, "No verbosity mode defined, defaulting to no Verbosity!") default: return errors.New("Bad Verbosity defined in config!") } switch c.QuantizationMode { case QuantizationOn: case QuantizationOff: case NothingDefined: c.Logger.Log(smartlogger.Warning, "No quantization mode defined, defaulting to QuantizationOff!") c.QuantizationMode = QuantizationOff default: return errors.New("Bad QuantizationMode defined in config!") } switch c.Input { case Raspivid: case File: case NothingDefined: 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!") } switch c.InputCodec { case H264: if c.Bitrate != "" && c.Quantization != "" { bitrate, err := strconv.Atoi(c.Bitrate) if err != nil { return errors.New("Something is wrong with bitrate in conig!") } quantization, err := strconv.Atoi(c.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 c.Quantization != "" { quantization, err := strconv.Atoi(c.Quantization) if err != nil { return errors.New("Something is wrong with quantization in config!") } if quantization > 0 || c.Bitrate == "" { return errors.New("Bad bitrate or quantization for mjpeg input!") } } case NothingDefined: c.Logger.Log(smartlogger.Warning, "No input codec defined, defaulting to h264!") c.InputCodec = H264 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!") } switch c.Output { case File: case Rtmp, FfmpegRtmp: if c.RtmpUrl == "" { c.Logger.Log(smartlogger.Info, "No RTMP URL: falling back to HTTP") c.Output = Http break } c.Logger.Log(smartlogger.Info, "Defaulting frames per clip to 1 for rtmp output!") c.FramesPerClip = 1 case NothingDefined: c.Logger.Log(smartlogger.Warning, "No output defined, defaulting to httpOut!") c.Output = defaultOutput fallthrough case Http: 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!") } switch c.Packetization { case None: case Mpegts: case Flv: case NothingDefined: 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!") } switch c.HorizontalFlip { case Yes: case No: case NothingDefined: 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!") } switch c.VerticalFlip { case Yes: case No: case NothingDefined: 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 { c.Logger.Log(smartlogger.Warning, "No FramesPerClip defined defined, defaulting to 1!") c.FramesPerClip = defaultFramesPerClip } if c.Width == "" { 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 { return errors.New("Bad width defined in config!") } } if c.Height == "" { 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 { return errors.New("Bad height defined in config!") } } if c.FrameRate == "" { 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 { return errors.New("Bad frame rate defined in config!") } } if c.Bitrate == "" { c.Logger.Log(smartlogger.Warning, "No bitrate defined, defaulting!") c.Bitrate = defaultBitrate } else { if integer, err := strconv.Atoi(c.Bitrate); integer < 0 || err != nil { return errors.New("Bad bitrate defined in config!") } } if c.Timeout == "" { 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 { return errors.New("Bad timeout defined in config!") } } if c.IntraRefreshPeriod == "" { 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 { return errors.New("Bad intra refresh defined in config!") } } if c.Quantization == "" { c.Logger.Log(smartlogger.Warning, "No quantization defined") c.Quantization = defaultQuantization } else { if integer, err := strconv.Atoi(c.Quantization); integer < 0 || integer > 51 || err != nil { return errors.New("Bad quantization defined in config!") } } return nil }