mirror of https://bitbucket.org/ausocean/av.git
revid: revid config to update geovision configuration using gvctrl
Added required new params to config structure, and therefore also added new defaults and validation checking. Also updated revid's update func so that we can control new parameters using vars. Now using gvctrl in startRTSPCamera function and interpreting revid config to configure camera.
This commit is contained in:
parent
ce6c12cce8
commit
8c1c192218
|
@ -109,7 +109,7 @@ func handleFlags() revid.Config {
|
||||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
|
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
|
||||||
inputCodecPtr = flag.String("InputCodec", "H264", "The codec of the input: H264, Mjpeg, PCM, ADPCM")
|
inputCodecPtr = flag.String("InputCodec", "H264", "The codec of the input: H264, Mjpeg, PCM, ADPCM")
|
||||||
inputPtr = flag.String("Input", "", "The input type: Raspivid, File, v4l, Audio, RTSP")
|
inputPtr = flag.String("Input", "", "The input type: Raspivid, File, v4l, Audio, RTSP")
|
||||||
rtspURLPtr = flag.String("RTSPURL", "", "The URL for an RTSP server.")
|
cameraIPPtr = flag.String("CameraIP", "", "The the IP of the RTSP server")
|
||||||
verbosityPtr = flag.String("Verbosity", "Info", "Verbosity: Debug, Info, Warning, Error, Fatal")
|
verbosityPtr = flag.String("Verbosity", "Info", "Verbosity: Debug, Info, Warning, Error, Fatal")
|
||||||
rtpAddrPtr = flag.String("RtpAddr", "", "Rtp destination address: <IP>:<port> (port is generally 6970-6999)")
|
rtpAddrPtr = flag.String("RtpAddr", "", "Rtp destination address: <IP>:<port> (port is generally 6970-6999)")
|
||||||
logPathPtr = flag.String("LogPath", defaultLogPath, "The log path")
|
logPathPtr = flag.String("LogPath", defaultLogPath, "The log path")
|
||||||
|
@ -231,7 +231,7 @@ func handleFlags() revid.Config {
|
||||||
netsender.ConfigFile = *configFilePtr
|
netsender.ConfigFile = *configFilePtr
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.RTSPURL = *rtspURLPtr
|
cfg.CameraIP = *cameraIPPtr
|
||||||
cfg.Rotation = *rotationPtr
|
cfg.Rotation = *rotationPtr
|
||||||
cfg.FlipHorizontal = *horizontalFlipPtr
|
cfg.FlipHorizontal = *horizontalFlipPtr
|
||||||
cfg.FlipVertical = *verticalFlipPtr
|
cfg.FlipVertical = *verticalFlipPtr
|
||||||
|
|
|
@ -63,6 +63,19 @@ var AutoWhiteBalanceModes = [...]string{
|
||||||
"horizon",
|
"horizon",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// quality represents video quality.
|
||||||
|
type quality int
|
||||||
|
|
||||||
|
// The different video qualities that can be used for variable bitrate when
|
||||||
|
// using the GeoVision camera.
|
||||||
|
const (
|
||||||
|
qualityStandard quality = iota
|
||||||
|
qualityFair
|
||||||
|
qualityGood
|
||||||
|
qualityGreat
|
||||||
|
qualityExcellent
|
||||||
|
)
|
||||||
|
|
||||||
// Enums to define inputs, outputs and codecs.
|
// Enums to define inputs, outputs and codecs.
|
||||||
const (
|
const (
|
||||||
// Indicates no option has been set.
|
// Indicates no option has been set.
|
||||||
|
@ -100,8 +113,11 @@ const (
|
||||||
defaultInputCodec = codecutil.H264
|
defaultInputCodec = codecutil.H264
|
||||||
defaultVerbosity = logger.Error
|
defaultVerbosity = logger.Error
|
||||||
defaultRtpAddr = "localhost:6970"
|
defaultRtpAddr = "localhost:6970"
|
||||||
defaultRTSPURL = "rtsp://admin:admin@192.168.1.50:8554/CH001.sdp"
|
defaultCameraIP = "192.168.1.50"
|
||||||
|
defaultVBR = false
|
||||||
|
defaultVBRQuality = qualityStandard
|
||||||
defaultBurstPeriod = 10 // Seconds
|
defaultBurstPeriod = 10 // Seconds
|
||||||
|
defaultVBRBitrate = 500 // kbps
|
||||||
|
|
||||||
// Raspivid video defaults.
|
// Raspivid video defaults.
|
||||||
defaultBrightness = 50
|
defaultBrightness = 50
|
||||||
|
@ -113,7 +129,7 @@ const (
|
||||||
defaultMinFrames = 100
|
defaultMinFrames = 100
|
||||||
defaultClipDuration = 0
|
defaultClipDuration = 0
|
||||||
defaultQuantization = 30
|
defaultQuantization = 30
|
||||||
defaultBitrate = 400000
|
defaultBitrate = 400
|
||||||
|
|
||||||
// Audio defaults.
|
// Audio defaults.
|
||||||
defaultAudioInputCodec = codecutil.ADPCM
|
defaultAudioInputCodec = codecutil.ADPCM
|
||||||
|
@ -152,7 +168,7 @@ type Config struct {
|
||||||
// File:
|
// File:
|
||||||
// Location must be specified in InputPath field.
|
// Location must be specified in InputPath field.
|
||||||
// RTSP:
|
// RTSP:
|
||||||
// RTSPURL must also be defined.
|
// CameraIP should also be defined.
|
||||||
Input uint8
|
Input uint8
|
||||||
|
|
||||||
// InputCodec defines the input codec we wish to use, and therefore defines the
|
// InputCodec defines the input codec we wish to use, and therefore defines the
|
||||||
|
@ -181,9 +197,9 @@ type Config struct {
|
||||||
// RTMP is to be used as an output.
|
// RTMP is to be used as an output.
|
||||||
RTMPURL string
|
RTMPURL string
|
||||||
|
|
||||||
// RTSPURL specifies the RTSP server URL for RTSP input. This must be defined
|
// CameraIP is the IP address of the camera in the case of the input camera
|
||||||
// when Input is RTSP.
|
// being an IP camera.
|
||||||
RTSPURL string
|
CameraIP string
|
||||||
|
|
||||||
// OutputPath defines the output destination for File output. This must be
|
// OutputPath defines the output destination for File output. This must be
|
||||||
// defined if File output is to be used.
|
// defined if File output is to be used.
|
||||||
|
@ -204,11 +220,27 @@ type Config struct {
|
||||||
// defined in /etc/netsender.conf.
|
// defined in /etc/netsender.conf.
|
||||||
HTTPAddress string
|
HTTPAddress string
|
||||||
|
|
||||||
// Quantization defines the quantization level, which may be a value between
|
// VBR indicates whether we wish to use constant or variable bitrate. If VBR
|
||||||
// 0-40. This will only take effect if the Quantize field is true and if we
|
// is true then we will use variable bitrate, and constant bitrate otherwise.
|
||||||
// are using Raspivid input.
|
// In the case of the Pi camera, variable bitrate quality is controlled by
|
||||||
|
// the Quantization parameter below. In the case of the GeoVision camera,
|
||||||
|
// variable bitrate quality is controlled by firstly the VBRQuality parameter
|
||||||
|
// and second the VBRBitrate parameter.
|
||||||
|
VBR bool
|
||||||
|
|
||||||
|
// Quantization defines the quantization level, which will determine variable
|
||||||
|
// bitrate quality in the case of input from the Pi Camera.
|
||||||
Quantization uint
|
Quantization uint
|
||||||
|
|
||||||
|
// VBRQuality describes the general quality of video from the GeoVision camera
|
||||||
|
// under variable bitrate. VBRQuality can be one 5 consts defined:
|
||||||
|
// qualityStandard, qualityFair, qualityGood, qualityGreat and qualityExcellent.
|
||||||
|
VBRQuality quality
|
||||||
|
|
||||||
|
// VBRBitrate describes maximal bitrate for the GeoVision camera when under
|
||||||
|
// variable bitrate.
|
||||||
|
VBRBitrate int
|
||||||
|
|
||||||
// MinFrames defines the frequency of key NAL units SPS, PPS and IDR in
|
// MinFrames defines the frequency of key NAL units SPS, PPS and IDR in
|
||||||
// number of NAL units. This will also determine the frequency of PSI if the
|
// number of NAL units. This will also determine the frequency of PSI if the
|
||||||
// output container is MPEG-TS. If ClipDuration is less than MinFrames,
|
// output container is MPEG-TS. If ClipDuration is less than MinFrames,
|
||||||
|
@ -251,7 +283,7 @@ type Config struct {
|
||||||
Rotation uint // Rotation defines the video rotation angle in degrees Raspivid input.
|
Rotation uint // Rotation defines the video rotation angle in degrees Raspivid input.
|
||||||
Height uint // Height defines the input video height Raspivid input.
|
Height uint // Height defines the input video height Raspivid input.
|
||||||
Width uint // Width defines the input video width Raspivid input.
|
Width uint // Width defines the input video width Raspivid input.
|
||||||
Bitrate uint // Bitrate specifies the input bitrate for Raspivid input.
|
Bitrate uint // Bitrate specifies the bitrate for constant bitrate in kbps.
|
||||||
FlipHorizontal bool // FlipHorizontal flips video horizontally for Raspivid input.
|
FlipHorizontal bool // FlipHorizontal flips video horizontally for Raspivid input.
|
||||||
FlipVertical bool // FlipVertial flips video vertically for Raspivid input.
|
FlipVertical bool // FlipVertial flips video vertically for Raspivid input.
|
||||||
|
|
||||||
|
@ -288,9 +320,9 @@ func (c *Config) Validate() error {
|
||||||
switch c.Input {
|
switch c.Input {
|
||||||
case Raspivid, V4L, File, Audio:
|
case Raspivid, V4L, File, Audio:
|
||||||
case RTSP:
|
case RTSP:
|
||||||
if c.RTSPURL == "" {
|
if c.CameraIP == "" {
|
||||||
c.Logger.Log(logger.Info, pkg+"no RTSPURL defined, defaulting", "RTSPURL", defaultRTSPURL)
|
c.Logger.Log(logger.Info, pkg+"no CameraIP defined, defaulting", "CameraIP", defaultCameraIP)
|
||||||
c.RTSPURL = defaultRTSPURL
|
c.CameraIP = defaultCameraIP
|
||||||
}
|
}
|
||||||
case NothingDefined:
|
case NothingDefined:
|
||||||
c.Logger.Log(logger.Info, pkg+"no input type defined, defaulting", "input", defaultInput)
|
c.Logger.Log(logger.Info, pkg+"no input type defined, defaulting", "input", defaultInput)
|
||||||
|
@ -481,6 +513,18 @@ func (c *Config) Validate() error {
|
||||||
c.MTSRBWriteTimeout = defaultMTSRBWriteTimeout
|
c.MTSRBWriteTimeout = defaultMTSRBWriteTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch c.VBRQuality {
|
||||||
|
case qualityStandard, qualityFair, qualityGood, qualityGreat, qualityExcellent:
|
||||||
|
default:
|
||||||
|
c.Logger.Log(logger.Info, pkg+"VBRQuality bad or unset, defaulting", "VBRQuality", defaultVBRQuality)
|
||||||
|
c.VBRQuality = defaultVBRQuality
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.VBRBitrate <= 0 {
|
||||||
|
c.Logger.Log(logger.Info, pkg+"VBRBitrate bad or unset, defaulting", "VBRBitrate", defaultVBRBitrate)
|
||||||
|
c.VBRBitrate = defaultVBRBitrate
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,19 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||||
|
"bitbucket.org/ausocean/av/input/gvctrl"
|
||||||
"bitbucket.org/ausocean/av/protocol/rtcp"
|
"bitbucket.org/ausocean/av/protocol/rtcp"
|
||||||
"bitbucket.org/ausocean/av/protocol/rtp"
|
"bitbucket.org/ausocean/av/protocol/rtp"
|
||||||
"bitbucket.org/ausocean/av/protocol/rtsp"
|
"bitbucket.org/ausocean/av/protocol/rtsp"
|
||||||
"bitbucket.org/ausocean/utils/logger"
|
"bitbucket.org/ausocean/utils/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: remove this when gvctrl has configurable user and pass.
|
||||||
|
const (
|
||||||
|
ipCamUser = "admin"
|
||||||
|
ipCamPass = "pass"
|
||||||
|
)
|
||||||
|
|
||||||
// startRaspivid sets up things for input from raspivid i.e. starts
|
// startRaspivid sets up things for input from raspivid i.e. starts
|
||||||
// a raspivid process and pipes it's data output.
|
// a raspivid process and pipes it's data output.
|
||||||
func (r *Revid) startRaspivid() (func() error, error) {
|
func (r *Revid) startRaspivid() (func() error, error) {
|
||||||
|
@ -58,7 +65,7 @@ func (r *Revid) startRaspivid() (func() error, error) {
|
||||||
"--timeout", disabled,
|
"--timeout", disabled,
|
||||||
"--width", fmt.Sprint(r.config.Width),
|
"--width", fmt.Sprint(r.config.Width),
|
||||||
"--height", fmt.Sprint(r.config.Height),
|
"--height", fmt.Sprint(r.config.Height),
|
||||||
"--bitrate", fmt.Sprint(r.config.Bitrate),
|
"--bitrate", fmt.Sprint(r.config.Bitrate * 1000), // Convert from kbps to bps.
|
||||||
"--framerate", fmt.Sprint(r.config.FrameRate),
|
"--framerate", fmt.Sprint(r.config.FrameRate),
|
||||||
"--rotation", fmt.Sprint(r.config.Rotation),
|
"--rotation", fmt.Sprint(r.config.Rotation),
|
||||||
"--brightness", fmt.Sprint(r.config.Brightness),
|
"--brightness", fmt.Sprint(r.config.Brightness),
|
||||||
|
@ -87,7 +94,7 @@ func (r *Revid) startRaspivid() (func() error, error) {
|
||||||
"--inline",
|
"--inline",
|
||||||
"--intra", fmt.Sprint(r.config.MinFrames),
|
"--intra", fmt.Sprint(r.config.MinFrames),
|
||||||
)
|
)
|
||||||
if r.config.Quantization != 0 {
|
if r.config.VBR {
|
||||||
args = append(args, "-qp", fmt.Sprint(r.config.Quantization))
|
args = append(args, "-qp", fmt.Sprint(r.config.Quantization))
|
||||||
}
|
}
|
||||||
case codecutil.MJPEG:
|
case codecutil.MJPEG:
|
||||||
|
@ -173,7 +180,36 @@ func (r *Revid) setupInputForFile() (func() error, error) {
|
||||||
// client is created from which RTP packets containing either h264/h265 can be
|
// client is created from which RTP packets containing either h264/h265 can be
|
||||||
// read by the selected lexer.
|
// read by the selected lexer.
|
||||||
func (r *Revid) startRTSPCamera() (func() error, error) {
|
func (r *Revid) startRTSPCamera() (func() error, error) {
|
||||||
rtspClt, local, remote, err := rtsp.NewClient(r.config.RTSPURL)
|
err := gvctrl.Set(
|
||||||
|
r.config.CameraIP,
|
||||||
|
gvctrl.CodecOut(
|
||||||
|
map[uint8]gvctrl.Codec{
|
||||||
|
codecutil.H264: gvctrl.CodecH264,
|
||||||
|
codecutil.H265: gvctrl.CodecH265,
|
||||||
|
codecutil.MJPEG: gvctrl.CodecMJPEG,
|
||||||
|
}[r.config.InputCodec],
|
||||||
|
),
|
||||||
|
gvctrl.Height(int(r.config.Height)),
|
||||||
|
gvctrl.FrameRate(int(r.config.FrameRate)),
|
||||||
|
gvctrl.VariableBitrate(r.config.VBR),
|
||||||
|
gvctrl.VBRQuality(
|
||||||
|
map[quality]gvctrl.Quality{
|
||||||
|
qualityStandard: gvctrl.QualityStandard,
|
||||||
|
qualityFair: gvctrl.QualityFair,
|
||||||
|
qualityGood: gvctrl.QualityGood,
|
||||||
|
qualityGreat: gvctrl.QualityGreat,
|
||||||
|
qualityExcellent: gvctrl.QualityExcellent,
|
||||||
|
}[r.config.VBRQuality],
|
||||||
|
),
|
||||||
|
gvctrl.VBRBitrate(r.config.VBRBitrate),
|
||||||
|
gvctrl.CBRBitrate(int(r.config.Bitrate)/1000),
|
||||||
|
gvctrl.Refresh(float64(r.config.MinFrames)/float64(r.config.FrameRate)),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not set IPCamera settings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rtspClt, local, remote, err := rtsp.NewClient("rtsp://" + ipCamUser + ":" + ipCamPass + "@" + r.config.CameraIP + ":8554/" + "CH002.sdp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -618,6 +618,27 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.config.MTSRBWriteTimeout = v
|
r.config.MTSRBWriteTimeout = v
|
||||||
|
case "VBR":
|
||||||
|
v, ok := map[string]bool{"true": true, "false": false}[strings.ToLower(value)]
|
||||||
|
if !ok {
|
||||||
|
r.config.Logger.Log(logger.Warning, pkg+"invalid VBR var", "value", value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
r.config.VBR = v
|
||||||
|
case "VBRQuality":
|
||||||
|
v, ok := map[string]quality{"standard": qualityStandard, "fair": qualityFair, "good": qualityGood, "great": qualityGreat, "excellent": qualityExcellent}[strings.ToLower(value)]
|
||||||
|
if !ok {
|
||||||
|
r.config.Logger.Log(logger.Warning, pkg+"invalid VBRQuality var", "value", value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
r.config.VBRQuality = v
|
||||||
|
case "VBRBitrate":
|
||||||
|
v, err := strconv.Atoi(value)
|
||||||
|
if err != nil || v <= 0 {
|
||||||
|
r.config.Logger.Log(logger.Warning, pkg+"invalid VBRBitrate var", "value", value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
r.config.VBRBitrate = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.config.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.config))
|
r.config.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.config))
|
||||||
|
|
Loading…
Reference in New Issue