diff --git a/revid/geovision.go b/revid/geovision.go index f801dc50..de029e7c 100644 --- a/revid/geovision.go +++ b/revid/geovision.go @@ -27,9 +27,14 @@ package revid import ( "errors" "fmt" + "time" "bitbucket.org/ausocean/av/codec/codecutil" "bitbucket.org/ausocean/av/input/gvctrl" + "bitbucket.org/ausocean/av/protocol/rtcp" + "bitbucket.org/ausocean/av/protocol/rtp" + "bitbucket.org/ausocean/av/protocol/rtsp" + "bitbucket.org/ausocean/utils/logger" ) const ( @@ -55,8 +60,11 @@ var ( type GeoVision struct { cfg Config + log Logger } +func NewGeovision(l Logger) *GeoVision { return &GeoVision{log: l} } + func (g *GeoVision) Set(c Config) error { var errs multiError if c.CameraIP == "" { @@ -139,5 +147,99 @@ func (g *GeoVision) Set(c Config) error { if err != nil { return fmt.Errorf("could not set IPCamera settings: %w", err) } + + // Give the camera some time to change it's configuration. + const setupDelay = 5 * time.Second + time.Sleep(setupDelay) + return multiError(errs) } + +func (g *GeoVision) Start() error { + rtspClt, local, remote, err := rtsp.NewClient("rtsp://" + ipCamUser + ":" + ipCamPass + "@" + g.cfg.CameraIP + ":8554/" + "CH002.sdp") + if err != nil { + return fmt.Errorf("could not create RTSP client: %w", err) + } + + g.log.Log(logger.Info, pkg+"created RTSP client") + + resp, err := rtspClt.Options() + if err != nil { + return fmt.Errorf("options request unsuccessful: %w", err) + } + g.log.Log(logger.Debug, pkg+"RTSP OPTIONS response", "response", resp.String()) + + resp, err = rtspClt.Describe() + if err != nil { + return fmt.Errorf("describe request unsuccessful: %w", err) + } + g.log.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 fmt.Errorf("setup request unsuccessful: %w", err) + } + g.log.Log(logger.Debug, pkg+"RTSP SETUP response", "response", resp.String()) + + rtpCltAddr, rtcpCltAddr, rtcpSvrAddr, err := formAddrs(local, remote, *resp) + if err != nil { + return fmt.Errorf("could not format addresses: %w", err) + } + + g.log.Log(logger.Info, pkg+"RTSP session setup complete") + + rtpClt, err := rtp.NewClient(rtpCltAddr) + if err != nil { + return fmt.Errorf("could not create RTP client: %w", err) + } + + rtcpClt, err := rtcp.NewClient(rtcpCltAddr, rtcpSvrAddr, rtpClt, g.log.Log) + if err != nil { + return fmt.Errorf("could not create RTCP client: %w", err) + } + + g.log.Log(logger.Info, pkg+"RTCP and RTP clients created") + + // Check errors from RTCP client until it has stopped running. + go func() { + for { + err, ok := <-rtcpClt.Err() + if ok { + g.log.Log(logger.Warning, pkg+"RTCP error", "error", err.Error()) + } else { + return + } + } + }() + + // Start the RTCP client. + rtcpClt.Start() + + g.log.Log(logger.Info, pkg+"RTCP client started") + + g.log.Log(logger.Info, pkg+"started input processor") + + resp, err = rtspClt.Play() + if err != nil { + return fmt.Errorf("play request unsuccessful: %w", err) + } + g.log.Log(logger.Debug, pkg+"RTSP server PLAY response", "response", resp.String()) + g.log.Log(logger.Info, pkg+"play requested, now receiving stream") + + return nil +} + +/* +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() + +g.log.Log(logger.Info, pkg+"RTP, RTSP and RTCP clients stopped and closed")*/