mirror of https://bitbucket.org/ausocean/av.git
revid: general bug fixing
Use http instead of https in gvctrl getLogin request. Gave RTP client a close method so that the conn can be closed after we're done with the client. Put timeout on reading from the RTP client PacketConn so that we don't hang on the ReadFrom call if the conn is closed. Closing the RTSP and RTP clients when startRTSPCamera is returned.
This commit is contained in:
parent
504179c03b
commit
f336a03d7a
|
@ -31,6 +31,7 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/ausocean/av/codec/h264/h264dec"
|
||||
|
@ -95,9 +96,9 @@ func (e *Extracter) Extract(dst io.Writer, src io.Reader, delay time.Duration) e
|
|||
buf := make([]byte, maxRTPSize)
|
||||
for {
|
||||
n, err := src.Read(buf)
|
||||
switch err {
|
||||
case nil: // Do nothing.
|
||||
case io.EOF:
|
||||
switch {
|
||||
case err == nil: // Do nothing.
|
||||
case err == io.EOF || err.(net.Error).Timeout():
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("source read error: %v\n", err)
|
||||
|
|
|
@ -52,7 +52,7 @@ const (
|
|||
// from which (as well as username and password) two hashes are generated.
|
||||
// The generated hex is encoded into a url encoded form and returned as a string.
|
||||
func getLogin(c *http.Client, id, host string) (string, error) {
|
||||
req, err := http.NewRequest("GET", "https://"+host+loginSubDir, nil)
|
||||
req, err := http.NewRequest("GET", "http://"+host+loginSubDir, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can't create GET request for log-in page: %v", err)
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ LICENSE
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Client describes an RTP client that can receive an RTP stream and implements
|
||||
|
@ -58,6 +60,7 @@ func NewClient(addr string) (*Client, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
@ -81,6 +84,11 @@ func (c *Client) Read(p []byte) (int, error) {
|
|||
return n, err
|
||||
}
|
||||
|
||||
// Close will close the RTP client's connection.
|
||||
func (c *Client) Close() error {
|
||||
return c.r.PacketConn.Close()
|
||||
}
|
||||
|
||||
// setSequence sets the most recently received sequence number, and updates the
|
||||
// cycles count if the sequence number has rolled over.
|
||||
func (c *Client) setSequence(s uint16) {
|
||||
|
@ -113,6 +121,11 @@ type PacketReader struct {
|
|||
|
||||
// Read implements io.Reader.
|
||||
func (r PacketReader) Read(b []byte) (int, error) {
|
||||
const readTimeout = 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)
|
||||
}
|
||||
n, _, err := r.PacketConn.ReadFrom(b)
|
||||
return n, err
|
||||
}
|
||||
|
|
|
@ -317,13 +317,13 @@ func (c *Config) Validate() error {
|
|||
c.Logger.Log(logger.Info, pkg+"bad LogLevel mode defined, defaulting", "LogLevel", defaultVerbosity)
|
||||
}
|
||||
|
||||
switch c.Input {
|
||||
case Raspivid, V4L, File, Audio:
|
||||
case RTSP:
|
||||
if c.CameraIP == "" {
|
||||
c.Logger.Log(logger.Info, pkg+"no CameraIP defined, defaulting", "CameraIP", defaultCameraIP)
|
||||
c.CameraIP = defaultCameraIP
|
||||
}
|
||||
|
||||
switch c.Input {
|
||||
case Raspivid, V4L, File, Audio, RTSP:
|
||||
case NothingDefined:
|
||||
c.Logger.Log(logger.Info, pkg+"no input type defined, defaulting", "input", defaultInput)
|
||||
c.Input = defaultInput
|
||||
|
|
|
@ -109,7 +109,7 @@ func (r *Revid) startRaspivid() (func() error, error) {
|
|||
}
|
||||
err = r.cmd.Start()
|
||||
if err != nil {
|
||||
r.config.Logger.Log(logger.Fatal, pkg+"cannot start raspivid", "error", err.Error())
|
||||
return nil, fmt.Errorf("could not start raspivid command: %w", err)
|
||||
}
|
||||
|
||||
r.wg.Add(1)
|
||||
|
@ -272,7 +272,16 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
|
|||
go r.processFrom(rtpClt, time.Second/time.Duration(r.config.FrameRate))
|
||||
|
||||
return func() error {
|
||||
rtspClt.Close()
|
||||
err := rtpClt.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not close RTP client: %w", err)
|
||||
}
|
||||
|
||||
err = rtspClt.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not close RTSP client: %w", err)
|
||||
}
|
||||
|
||||
rtcpClt.Stop()
|
||||
return nil
|
||||
}, nil
|
||||
|
|
|
@ -134,17 +134,12 @@ func (r *Revid) Config() Config {
|
|||
return r.config
|
||||
}
|
||||
|
||||
// TODO(Saxon): put more thought into error severity.
|
||||
// TODO(Saxon): put more thought into error severity and how to handle these.
|
||||
func (r *Revid) handleErrors() {
|
||||
for {
|
||||
err := <-r.err
|
||||
if err != nil {
|
||||
r.config.Logger.Log(logger.Error, pkg+"async error", "error", err.Error())
|
||||
r.Stop()
|
||||
err = r.Start()
|
||||
if err != nil {
|
||||
r.config.Logger.Log(logger.Error, pkg+"failed to restart revid", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +357,6 @@ func (r *Revid) Start() error {
|
|||
}
|
||||
r.closeInput, err = r.setupInput()
|
||||
if err != nil {
|
||||
r.Stop()
|
||||
return err
|
||||
}
|
||||
r.running = true
|
||||
|
@ -394,12 +388,17 @@ func (r *Revid) Stop() {
|
|||
if err != nil {
|
||||
r.config.Logger.Log(logger.Error, pkg+"failed to close pipeline", "error", err.Error())
|
||||
}
|
||||
r.config.Logger.Log(logger.Info, pkg+"closed pipeline")
|
||||
|
||||
if r.cmd != nil && r.cmd.Process != nil {
|
||||
r.config.Logger.Log(logger.Info, pkg+"killing input proccess")
|
||||
r.cmd.Process.Kill()
|
||||
}
|
||||
r.config.Logger.Log(logger.Info, pkg+"waiting for routines to close")
|
||||
|
||||
r.wg.Wait()
|
||||
|
||||
r.config.Logger.Log(logger.Info, pkg+"revid stopped")
|
||||
r.running = false
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue