From 94b089d1e3223a8f28cdddb9ee45c7c801420f75 Mon Sep 17 00:00:00 2001 From: Alexey Khit Date: Mon, 23 Jan 2023 21:14:52 +0300 Subject: [PATCH] Fix bug in URL for D-Link cameras --- pkg/rtsp/conn.go | 46 +++---------------------------- pkg/rtsp/helpers.go | 63 +++++++++++++++++++++++++++++++++++++++++++ pkg/rtsp/rtsp_test.go | 12 +++++++++ 3 files changed, 78 insertions(+), 43 deletions(-) create mode 100644 pkg/rtsp/helpers.go create mode 100644 pkg/rtsp/rtsp_test.go diff --git a/pkg/rtsp/conn.go b/pkg/rtsp/conn.go index ed3c41de..39703673 100644 --- a/pkg/rtsp/conn.go +++ b/pkg/rtsp/conn.go @@ -2,7 +2,6 @@ package rtsp import ( "bufio" - "bytes" "crypto/tls" "encoding/binary" "errors" @@ -281,7 +280,7 @@ func (c *Conn) Options() error { } if val := res.Header.Get("Content-Base"); val != "" { - c.URL, err = url.Parse(val) + c.URL, err = urlParse(val) if err != nil { return err } @@ -311,7 +310,7 @@ func (c *Conn) Describe() error { } if val := res.Header.Get("Content-Base"); val != "" { - c.URL, err = url.Parse(val) + c.URL, err = urlParse(val) if err != nil { return err } @@ -380,7 +379,7 @@ func (c *Conn) SetupMedia( } rawURL += media.Control } - trackURL, err := url.Parse(rawURL) + trackURL, err := urlParse(rawURL) if err != nil { return nil, err } @@ -882,42 +881,3 @@ func (c *Conn) bindTrack( return track.Bind(push) } - -type RTCP struct { - Channel byte - Header rtcp.Header - Packets []rtcp.Packet -} - -const sdpHeader = `v=0 -o=- 0 0 IN IP4 0.0.0.0 -s=- -t=0 0` - -func UnmarshalSDP(rawSDP []byte) ([]*streamer.Media, error) { - medias, err := streamer.UnmarshalSDP(rawSDP) - if err != nil { - // fix SDP header for some cameras - i := bytes.Index(rawSDP, []byte("\nm=")) - if i > 0 { - rawSDP = append([]byte(sdpHeader), rawSDP[i:]...) - medias, err = streamer.UnmarshalSDP(rawSDP) - } - if err != nil { - return nil, err - } - } - - // fix bug in ONVIF spec - // https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec-v241.pdf - for _, media := range medias { - switch media.Direction { - case streamer.DirectionRecvonly, "": - media.Direction = streamer.DirectionSendonly - case streamer.DirectionSendonly: - media.Direction = streamer.DirectionRecvonly - } - } - - return medias, nil -} diff --git a/pkg/rtsp/helpers.go b/pkg/rtsp/helpers.go new file mode 100644 index 00000000..3a7c0dc8 --- /dev/null +++ b/pkg/rtsp/helpers.go @@ -0,0 +1,63 @@ +package rtsp + +import ( + "bytes" + "github.com/AlexxIT/go2rtc/pkg/streamer" + "github.com/pion/rtcp" + "net/url" + "strings" +) + +type RTCP struct { + Channel byte + Header rtcp.Header + Packets []rtcp.Packet +} + +const sdpHeader = `v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=- +t=0 0` + +func UnmarshalSDP(rawSDP []byte) ([]*streamer.Media, error) { + medias, err := streamer.UnmarshalSDP(rawSDP) + if err != nil { + // fix SDP header for some cameras + i := bytes.Index(rawSDP, []byte("\nm=")) + if i > 0 { + rawSDP = append([]byte(sdpHeader), rawSDP[i:]...) + medias, err = streamer.UnmarshalSDP(rawSDP) + } + if err != nil { + return nil, err + } + } + + // fix bug in ONVIF spec + // https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec-v241.pdf + for _, media := range medias { + switch media.Direction { + case streamer.DirectionRecvonly, "": + media.Direction = streamer.DirectionSendonly + case streamer.DirectionSendonly: + media.Direction = streamer.DirectionRecvonly + } + } + + return medias, nil +} + +// urlParse fix bug in URL from D-Link camera: +// Content-Base: rtsp://::ffff:192.168.1.123/onvif/profile.1/ +func urlParse(rawURL string) (*url.URL, error) { + u, err := url.Parse(rawURL) + if err != nil && strings.HasSuffix(err.Error(), "after host") { + if i1 := strings.Index(rawURL, "://"); i1 > 0 { + if i2 := strings.IndexByte(rawURL[i1+3:], '/'); i2 > 0 { + return urlParse(rawURL[:i1+3+i2] + ":" + rawURL[i1+3+i2:]) + } + } + } + + return u, err +} diff --git a/pkg/rtsp/rtsp_test.go b/pkg/rtsp/rtsp_test.go new file mode 100644 index 00000000..93b2e930 --- /dev/null +++ b/pkg/rtsp/rtsp_test.go @@ -0,0 +1,12 @@ +package rtsp + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestURLParse(t *testing.T) { + base := "rtsp://::ffff:192.168.1.123/onvif/profile.1/" + _, err := urlParse(base) + assert.Empty(t, err) +}