revid: fixing some more bugs

Fixed H264 RTP extractor. Fine tuned some timing regarding geovision setup. Added some more
logging to geovision setup.
This commit is contained in:
Saxon 2019-10-23 12:48:22 +10:30
parent f336a03d7a
commit 38cfad7b67
8 changed files with 52 additions and 21 deletions

View File

@ -158,7 +158,7 @@ func handleFlags() revid.Config {
cfg.LogLevel = defaultLogVerbosity
}
log = logger.New(cfg.LogLevel, &smartlogger.New(*logPathPtr).LogRoller)
log = logger.New(cfg.LogLevel, &smartlogger.New(*logPathPtr).LogRoller, true)
cfg.Logger = log

View File

@ -31,7 +31,6 @@ import (
"encoding/binary"
"fmt"
"io"
"net"
"time"
"bitbucket.org/ausocean/av/codec/h264/h264dec"
@ -98,7 +97,7 @@ func (e *Extracter) Extract(dst io.Writer, src io.Reader, delay time.Duration) e
n, err := src.Read(buf)
switch {
case err == nil: // Do nothing.
case err == io.EOF || err.(net.Error).Timeout():
case err == io.EOF:
return nil
default:
return fmt.Errorf("source read error: %v\n", err)
@ -208,7 +207,7 @@ func (e *Extracter) handleFUA(d []byte) {
func (e *Extracter) writeWithPrefix(d []byte) {
e.toWrite = append(e.toWrite, d...)
curType, _ := NALType(e.toWrite)
if e.buf.Len() != 0 && (curType == h264dec.NALTypeIDR || curType == h264dec.NALTypeNonIDR) {
if e.buf.Len() != 0 && (curType == h264dec.NALTypeSPS || curType == h264dec.NALTypeIDR || curType == h264dec.NALTypeNonIDR) {
e.buf.WriteTo(e.dst)
e.buf.Reset()
e.buf.Write(aud)

3
go.mod
View File

@ -5,7 +5,7 @@ go 1.13
require (
bitbucket.org/ausocean/iot v1.2.7
bitbucket.org/ausocean/test v0.0.0-20190821085226-7a524f2344ba
bitbucket.org/ausocean/utils v1.2.9
bitbucket.org/ausocean/utils v1.2.10
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480
@ -13,5 +13,6 @@ require (
github.com/mewkiz/flac v1.0.5
github.com/pkg/errors v0.8.1
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e
gocv.io/x/gocv v0.21.0
gopkg.in/yaml.v2 v2.2.2 // indirect
)

7
go.sum
View File

@ -1,15 +1,20 @@
bitbucket.org/ausocean/av v0.0.0-20190416003121-6ee286e98874/go.mod h1:DxZEprrNNQ2slHKAQVUHryDaWc5CbjxyHAvomhzg+AE=
bitbucket.org/ausocean/av/input/gvctrl v0.0.0-20191017223116-ce6c12cce8cd h1:L99pvZZtdy3v54ym6GswYi8SOGgz+4Tr8hiIOI+nSiQ=
bitbucket.org/ausocean/av/input/gvctrl v0.0.0-20191017223116-ce6c12cce8cd/go.mod h1:Hg522DOVaj23J7CIxknCxmNsLGdg1iZ+Td1FDcTOdLQ=
bitbucket.org/ausocean/iot v1.2.4/go.mod h1:5HVLgPHccW2PxS7WDUQO6sKWMgk3Vfze/7d5bHs8EWU=
bitbucket.org/ausocean/iot v1.2.6 h1:KAAY1KZDbyOpoKajT1dM8BawupHiW9hUOelseSV1Ptc=
bitbucket.org/ausocean/iot v1.2.6/go.mod h1:71AYHh8yGZ8XyzDBskwIWMF+8E8ORagXpXE24wlhoE0=
bitbucket.org/ausocean/iot v1.2.7 h1:dZgrmVtuXnzHgybDthn0bYgAJms9euTONXBsqsx9g5M=
bitbucket.org/ausocean/iot v1.2.7/go.mod h1:aAWgPo2f8sD2OPmxae1E5/iD9+tKY/iW4pcQMQXUvHM=
bitbucket.org/ausocean/test v0.0.0-20190821085226-7a524f2344ba/go.mod h1:MbKtu9Pu8l3hiVGX6ep8S1VwAVY5uCbifCFOYsm914w=
bitbucket.org/ausocean/utils v0.0.0-20190408050157-66d3b4d4041e/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
bitbucket.org/ausocean/utils v1.2.6/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
bitbucket.org/ausocean/utils v1.2.8 h1:hyxAIqYBqjqCguG+6A/kKyrAihyeUt2LziZg6CH0gLU=
bitbucket.org/ausocean/utils v1.2.8/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
bitbucket.org/ausocean/utils v1.2.9 h1:g45C6KCNvCLOGFv+ZnmDbQOOdnwpIsvzuNOD141CTVI=
bitbucket.org/ausocean/utils v1.2.9/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
bitbucket.org/ausocean/utils v1.2.10 h1:JTS7n+K+0o/FQFWKjdGgA1ElZ4TQu9aHX3wTJXOayXw=
bitbucket.org/ausocean/utils v1.2.10/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7 h1:LdOc9B9Bj6LEsKiXShkLA3/kpxXb6LJpH+ekU2krbzw=
@ -55,6 +60,8 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
gocv.io/x/gocv v0.21.0 h1:dVjagrupZrfCRY0qPEaYWgoNMRpBel6GYDH4mvQOK8Y=
gocv.io/x/gocv v0.21.0/go.mod h1:Rar2PS6DV+T4FL+PM535EImD/h13hGVaHhnCu1xarBs=
golang.org/x/sys v0.0.0-20190305064518-30e92a19ae4a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -121,7 +121,7 @@ type PacketReader struct {
// Read implements io.Reader.
func (r PacketReader) Read(b []byte) (int, error) {
const readTimeout = time.Second
const readTimeout = 5 * time.Second
err := r.PacketConn.SetReadDeadline(time.Now().Add(readTimeout))
if err != nil {
return 0, fmt.Errorf("could not set read deadline for PacketConn: %w", err)

View File

@ -133,10 +133,11 @@ func (r *Revid) startV4L() (func() error, error) {
"-r", fmt.Sprint(r.config.FrameRate),
}
br := r.config.Bitrate * 1000
args = append(args,
"-b:v", fmt.Sprint(r.config.Bitrate),
"-maxrate", fmt.Sprint(r.config.Bitrate),
"-bufsize", fmt.Sprint(r.config.Bitrate/2),
"-b:v", fmt.Sprint(br),
"-maxrate", fmt.Sprint(br),
"-bufsize", fmt.Sprint(br/2),
"-s", fmt.Sprintf("%dx%d", r.config.Width, r.config.Height),
"-",
)
@ -179,7 +180,12 @@ func (r *Revid) setupInputForFile() (func() error, error) {
// startRTSPCamera uses RTSP to request an RTP stream from an IP camera. An RTP
// client is created from which RTP packets containing either h264/h265 can be
// read by the selected lexer.
//
// TODO(saxon): this function should really be startGeoVision. It's much too
// specific to be called startRTSPCamera.
func (r *Revid) startRTSPCamera() (func() error, error) {
r.config.Logger.Log(logger.Info, pkg+"starting geovision...")
err := gvctrl.Set(
r.config.CameraIP,
gvctrl.CodecOut(
@ -202,45 +208,48 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
}[r.config.VBRQuality],
),
gvctrl.VBRBitrate(r.config.VBRBitrate),
gvctrl.CBRBitrate(int(r.config.Bitrate)/1000),
gvctrl.CBRBitrate(int(r.config.Bitrate)),
gvctrl.Refresh(float64(r.config.MinFrames)/float64(r.config.FrameRate)),
)
if err != nil {
return nil, fmt.Errorf("could not set IPCamera settings: %w", err)
}
r.config.Logger.Log(logger.Info, pkg+"completed geovision configuration")
time.Sleep(5 * time.Second)
rtspClt, local, remote, err := rtsp.NewClient("rtsp://" + ipCamUser + ":" + ipCamPass + "@" + r.config.CameraIP + ":8554/" + "CH002.sdp")
if err != nil {
return nil, err
}
r.config.Logger.Log(logger.Info, pkg+"created RTSP client")
resp, err := rtspClt.Options()
if err != nil {
return nil, err
}
r.config.Logger.Log(logger.Info, pkg+"RTSP OPTIONS response", "response", resp.String())
r.config.Logger.Log(logger.Debug, pkg+"RTSP OPTIONS response", "response", resp.String())
resp, err = rtspClt.Describe()
if err != nil {
return nil, err
}
r.config.Logger.Log(logger.Info, pkg+"RTSP DESCRIBE response", "response", resp.String())
r.config.Logger.Log(logger.Debug, pkg+"RTSP DESCRIBE response", "response", resp.String())
resp, err = rtspClt.Setup("track1", fmt.Sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPort, rtcpPort))
if err != nil {
return nil, err
}
r.config.Logger.Log(logger.Info, pkg+"RTSP SETUP response", "response", resp.String())
r.config.Logger.Log(logger.Debug, pkg+"RTSP SETUP response", "response", resp.String())
rtpCltAddr, rtcpCltAddr, rtcpSvrAddr, err := formAddrs(local, remote, *resp)
if err != nil {
return nil, err
}
resp, err = rtspClt.Play()
if err != nil {
return nil, err
}
r.config.Logger.Log(logger.Info, pkg+"RTSP server PLAY response", "response", resp.String())
r.config.Logger.Log(logger.Info, pkg+"RTSP session setup complete")
rtpClt, err := rtp.NewClient(rtpCltAddr)
if err != nil {
@ -252,6 +261,8 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
return nil, err
}
r.config.Logger.Log(logger.Info, pkg+"RTCP and RTP clients created")
// Check errors from RTCP client until it has stopped running.
go func() {
for {
@ -267,10 +278,21 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
// Start the RTCP client.
rtcpClt.Start()
r.config.Logger.Log(logger.Info, pkg+"RTCP client started")
// Start reading data from the RTP client.
r.wg.Add(1)
go r.processFrom(rtpClt, time.Second/time.Duration(r.config.FrameRate))
r.config.Logger.Log(logger.Info, pkg+"started input processor")
resp, err = rtspClt.Play()
if err != nil {
return nil, err
}
r.config.Logger.Log(logger.Debug, pkg+"RTSP server PLAY response", "response", resp.String())
r.config.Logger.Log(logger.Info, pkg+"play requested, now receiving stream")
return func() error {
err := rtpClt.Close()
if err != nil {
@ -283,6 +305,8 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
}
rtcpClt.Stop()
r.config.Logger.Log(logger.Info, pkg+"RTP, RTSP and RTCP clients stopped and closed")
return nil
}, nil
}
@ -319,8 +343,7 @@ func parseSvrRTCPPort(resp rtsp.Response) (int, error) {
// processFrom is run as a routine to read from a input data source, lex and
// then send individual access units to revid's encoders.
func (r *Revid) processFrom(read io.Reader, delay time.Duration) {
r.config.Logger.Log(logger.Info, pkg+"reading input data")
r.err <- r.lexTo(r.encoders, read, delay)
r.config.Logger.Log(logger.Info, pkg+"finished reading input data")
r.config.Logger.Log(logger.Info, pkg+"finished lexing")
r.wg.Done()
}

View File

@ -62,7 +62,7 @@ const (
defaultServerRTCPPort = 17301
)
const pkg = "revid:"
const pkg = "revid: "
type Logger interface {
SetLevel(int8)

View File

@ -219,6 +219,7 @@ func (s *mtsSender) output() {
chunk = nil
continue
}
s.log(logger.Debug, pkg+"mtsSender: writing")
_, err = s.dst.Write(chunk.Bytes())
if err != nil {
s.repairer.Failed()