Browse Source

update gortsplib

pull/643/head
aler9 5 years ago
parent
commit
509bed355a
  1. 2
      README.md
  2. 2
      go.mod
  3. 4
      go.sum
  4. 11
      internal/conf/conf.go
  5. 3
      internal/conf/conf_test.go
  6. 23
      internal/conf/protocol.go
  7. 22
      internal/conf/sourceprotocol.go
  8. 5
      internal/core/core.go
  9. 25
      internal/core/rtsp_server_test.go
  10. 38
      internal/core/rtsp_session.go
  11. 2
      internal/core/rtsp_source.go
  12. 2
      rtsp-simple-server.yml

2
README.md

@ -506,7 +506,7 @@ In some scenarios, the server can send incomplete or corrupted frames. This can
readBufferCount: 1024 readBufferCount: 1024
``` ```
* The stream throughput is too big and the stream can't be sent correctly with the UDP stream protocol. UDP is more performant, faster and more efficient than TCP, but doesn't have a retransmission mechanism, that is needed in case of streams that need a large bandwidth. A solution consists in switching to TCP: * The stream throughput is too big and the stream can't be sent correctly with the UDP transport. UDP is more performant, faster and more efficient than TCP, but doesn't have a retransmission mechanism, that is needed in case of streams that need a large bandwidth. A solution consists in switching to TCP:
```yml ```yml
protocols: [tcp] protocols: [tcp]

2
go.mod

@ -5,7 +5,7 @@ go 1.16
require ( require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/aler9/gortsplib v0.0.0-20211001120239-c084f1b0f3b7 github.com/aler9/gortsplib v0.0.0-20211022160112-22501a39ddf6
github.com/asticode/go-astits v1.10.0 github.com/asticode/go-astits v1.10.0
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.7.2 github.com/gin-gonic/gin v1.7.2

4
go.sum

@ -2,8 +2,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/aler9/gortsplib v0.0.0-20211001120239-c084f1b0f3b7 h1:MV3JKPe6Tqf1ZwtJRSopzzugatjVRzLsHXI9BgTq4qM= github.com/aler9/gortsplib v0.0.0-20211022160112-22501a39ddf6 h1:dccH0/W0hfxXt054maCTjf96V4e5O9KJCH8cuNlYFck=
github.com/aler9/gortsplib v0.0.0-20211001120239-c084f1b0f3b7/go.mod h1:fyQrQyHo8QvdR/h357tkv1g36VesZlzEPsdAu2VrHHc= github.com/aler9/gortsplib v0.0.0-20211022160112-22501a39ddf6/go.mod h1:fyQrQyHo8QvdR/h357tkv1g36VesZlzEPsdAu2VrHHc=
github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927 h1:95mXJ5fUCYpBRdSOnLAQAdJHHKxxxJrVCiaqDi965YQ= github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927 h1:95mXJ5fUCYpBRdSOnLAQAdJHHKxxxJrVCiaqDi965YQ=
github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927/go.mod h1:vzuE21rowz+lT1NGsWbreIvYulgBpCGnQyeTyFblUHc= github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927/go.mod h1:vzuE21rowz+lT1NGsWbreIvYulgBpCGnQyeTyFblUHc=
github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8= github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8=

11
internal/conf/conf.go

@ -9,6 +9,7 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/headers" "github.com/aler9/gortsplib/pkg/headers"
"golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/nacl/secretbox"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -261,15 +262,15 @@ func (conf *Conf) CheckAndFillMissing() error {
if len(conf.Protocols) == 0 { if len(conf.Protocols) == 0 {
conf.Protocols = Protocols{ conf.Protocols = Protocols{
ProtocolUDP: {}, Protocol(gortsplib.TransportUDP): {},
ProtocolMulticast: {}, Protocol(gortsplib.TransportUDPMulticast): {},
ProtocolTCP: {}, Protocol(gortsplib.TransportTCP): {},
} }
} }
if conf.Encryption == EncryptionStrict { if conf.Encryption == EncryptionStrict {
if _, ok := conf.Protocols[ProtocolUDP]; ok { if _, ok := conf.Protocols[Protocol(gortsplib.TransportUDP)]; ok {
return fmt.Errorf("strict encryption can't be used with the UDP stream protocol") return fmt.Errorf("strict encryption can't be used with the UDP transport")
} }
} }

3
internal/conf/conf_test.go

@ -9,6 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/aler9/gortsplib"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/nacl/secretbox"
@ -101,7 +102,7 @@ func TestConfFromFileAndEnv(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, true, hasFile) require.Equal(t, true, hasFile)
require.Equal(t, Protocols{ProtocolTCP: {}}, conf.Protocols) require.Equal(t, Protocols{Protocol(gortsplib.TransportTCP): {}}, conf.Protocols)
pa, ok := conf.Paths["cam1"] pa, ok := conf.Paths["cam1"]
require.Equal(t, true, ok) require.Equal(t, true, ok)

23
internal/conf/protocol.go

@ -5,18 +5,13 @@ import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
)
// Protocol is a RTSP stream protocol.
type Protocol int
// supported RTSP protocols. "github.com/aler9/gortsplib"
const (
ProtocolUDP Protocol = iota
ProtocolMulticast
ProtocolTCP
) )
// Protocol is a RTSP transport.
type Protocol gortsplib.Transport
// Protocols is the protocols parameter. // Protocols is the protocols parameter.
type Protocols map[Protocol]struct{} type Protocols map[Protocol]struct{}
@ -29,10 +24,10 @@ func (d Protocols) MarshalJSON() ([]byte, error) {
var v string var v string
switch p { switch p {
case ProtocolUDP: case Protocol(gortsplib.TransportUDP):
v = "udp" v = "udp"
case ProtocolMulticast: case Protocol(gortsplib.TransportUDPMulticast):
v = "multicast" v = "multicast"
default: default:
@ -60,13 +55,13 @@ func (d *Protocols) UnmarshalJSON(b []byte) error {
for _, proto := range in { for _, proto := range in {
switch proto { switch proto {
case "udp": case "udp":
(*d)[ProtocolUDP] = struct{}{} (*d)[Protocol(gortsplib.TransportUDP)] = struct{}{}
case "multicast": case "multicast":
(*d)[ProtocolMulticast] = struct{}{} (*d)[Protocol(gortsplib.TransportUDPMulticast)] = struct{}{}
case "tcp": case "tcp":
(*d)[ProtocolTCP] = struct{}{} (*d)[Protocol(gortsplib.TransportTCP)] = struct{}{}
default: default:
return fmt.Errorf("invalid protocol: %s", proto) return fmt.Errorf("invalid protocol: %s", proto)

22
internal/conf/sourceprotocol.go

@ -9,21 +9,21 @@ import (
// SourceProtocol is the sourceProtocol parameter. // SourceProtocol is the sourceProtocol parameter.
type SourceProtocol struct { type SourceProtocol struct {
*gortsplib.ClientProtocol *gortsplib.Transport
} }
// MarshalJSON marshals a SourceProtocol into JSON. // MarshalJSON marshals a SourceProtocol into JSON.
func (d SourceProtocol) MarshalJSON() ([]byte, error) { func (d SourceProtocol) MarshalJSON() ([]byte, error) {
var out string var out string
if d.ClientProtocol == nil { if d.Transport == nil {
out = "automatic" out = "automatic"
} else { } else {
switch *d.ClientProtocol { switch *d.Transport {
case gortsplib.ClientProtocolUDP: case gortsplib.TransportUDP:
out = "udp" out = "udp"
case gortsplib.ClientProtocolMulticast: case gortsplib.TransportUDPMulticast:
out = "multicast" out = "multicast"
default: default:
@ -43,16 +43,16 @@ func (d *SourceProtocol) UnmarshalJSON(b []byte) error {
switch in { switch in {
case "udp": case "udp":
v := gortsplib.ClientProtocolUDP v := gortsplib.TransportUDP
d.ClientProtocol = &v d.Transport = &v
case "multicast": case "multicast":
v := gortsplib.ClientProtocolMulticast v := gortsplib.TransportUDPMulticast
d.ClientProtocol = &v d.Transport = &v
case "tcp": case "tcp":
v := gortsplib.ClientProtocolTCP v := gortsplib.TransportTCP
d.ClientProtocol = &v d.Transport = &v
case "automatic": case "automatic":

5
internal/core/core.go

@ -7,6 +7,7 @@ import (
"reflect" "reflect"
"sync/atomic" "sync/atomic"
"github.com/aler9/gortsplib"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gopkg.in/alecthomas/kingpin.v2" "gopkg.in/alecthomas/kingpin.v2"
@ -240,8 +241,8 @@ func (p *Core) createResources(initial bool) error {
(p.conf.Encryption == conf.EncryptionNo || (p.conf.Encryption == conf.EncryptionNo ||
p.conf.Encryption == conf.EncryptionOptional) { p.conf.Encryption == conf.EncryptionOptional) {
if p.rtspServer == nil { if p.rtspServer == nil {
_, useUDP := p.conf.Protocols[conf.ProtocolUDP] _, useUDP := p.conf.Protocols[conf.Protocol(gortsplib.TransportUDP)]
_, useMulticast := p.conf.Protocols[conf.ProtocolMulticast] _, useMulticast := p.conf.Protocols[conf.Protocol(gortsplib.TransportUDPMulticast)]
p.rtspServer, err = newRTSPServer( p.rtspServer, err = newRTSPServer(
p.ctx, p.ctx,
p.conf.RTSPAddress, p.conf.RTSPAddress,

25
internal/core/rtsp_server_test.go

@ -175,8 +175,9 @@ func TestRTSPServerPublishRead(t *testing.T) {
}() }()
cnt2, err := newContainer("gstreamer", "read", []string{ cnt2, err := newContainer("gstreamer", "read", []string{
"rtspsrc location=" + proto + "://127.0.0.1:" + port + "/teststream protocols=" + ps + "rtspsrc location=" + proto + "://127.0.0.1:" + port + "/teststream " +
" tls-validation-flags=0 latency=0 " + "protocols=" + ps + " " +
"tls-validation-flags=0 latency=0 " +
"! application/x-rtp,media=video ! decodebin ! exitafterframe ! fakesink", "! application/x-rtp,media=video ! decodebin ! exitafterframe ! fakesink",
}) })
require.NoError(t, err) require.NoError(t, err)
@ -525,8 +526,8 @@ func TestRTSPServerNonCompliantFrameSize(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
client := &gortsplib.Client{ client := &gortsplib.Client{
Protocol: func() *gortsplib.ClientProtocol { Transport: func() *gortsplib.Transport {
v := gortsplib.ClientProtocolTCP v := gortsplib.TransportTCP
return &v return &v
}(), }(),
ReadBufferSize: 4500, ReadBufferSize: 4500,
@ -576,8 +577,8 @@ func TestRTSPServerNonCompliantFrameSize(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
client := &gortsplib.Client{ client := &gortsplib.Client{
Protocol: func() *gortsplib.ClientProtocol { Transport: func() *gortsplib.Transport {
v := gortsplib.ClientProtocolTCP v := gortsplib.TransportTCP
return &v return &v
}(), }(),
ReadBufferSize: 4500, ReadBufferSize: 4500,
@ -810,9 +811,9 @@ wait
Header: base.Header{ Header: base.Header{
"CSeq": base.HeaderValue{"2"}, "CSeq": base.HeaderValue{"2"},
"Transport": headers.Transport{ "Transport": headers.Transport{
Protocol: base.StreamProtocolTCP, Protocol: headers.TransportProtocolTCP,
Delivery: func() *base.StreamDelivery { Delivery: func() *headers.TransportDelivery {
v := base.StreamDeliveryUnicast v := headers.TransportDeliveryUnicast
return &v return &v
}(), }(),
Mode: func() *headers.TransportMode { Mode: func() *headers.TransportMode {
@ -863,9 +864,9 @@ wait
Header: base.Header{ Header: base.Header{
"CSeq": base.HeaderValue{"1"}, "CSeq": base.HeaderValue{"1"},
"Transport": headers.Transport{ "Transport": headers.Transport{
Protocol: base.StreamProtocolTCP, Protocol: headers.TransportProtocolTCP,
Delivery: func() *base.StreamDelivery { Delivery: func() *headers.TransportDelivery {
v := base.StreamDeliveryUnicast v := headers.TransportDeliveryUnicast
return &v return &v
}(), }(),
Mode: func() *headers.TransportMode { Mode: func() *headers.TransportMode {

38
internal/core/rtsp_session.go

@ -96,13 +96,6 @@ func (s *rtspSession) RemoteAddr() net.Addr {
return s.author.NetConn().RemoteAddr() return s.author.NetConn().RemoteAddr()
} }
func (s *rtspSession) displayedProtocol() string {
if *s.ss.SetuppedDelivery() == base.StreamDeliveryMulticast {
return "UDP-multicast"
}
return s.ss.SetuppedProtocol().String()
}
func (s *rtspSession) log(level logger.Level, format string, args ...interface{}) { func (s *rtspSession) log(level logger.Level, format string, args ...interface{}) {
s.parent.Log(level, "[session %s] "+format, append([]interface{}{s.id}, args...)...) s.parent.Log(level, "[session %s] "+format, append([]interface{}{s.id}, args...)...)
} }
@ -174,24 +167,27 @@ func (s *rtspSession) OnAnnounce(c *rtspConn, ctx *gortsplib.ServerHandlerOnAnno
// OnSetup is called by rtspServer. // OnSetup is called by rtspServer.
func (s *rtspSession) OnSetup(c *rtspConn, ctx *gortsplib.ServerHandlerOnSetupCtx, func (s *rtspSession) OnSetup(c *rtspConn, ctx *gortsplib.ServerHandlerOnSetupCtx,
) (*base.Response, *gortsplib.ServerStream, error) { ) (*base.Response, *gortsplib.ServerStream, error) {
if ctx.Transport.Protocol == base.StreamProtocolUDP { switch ctx.Transport {
if _, ok := s.protocols[conf.ProtocolUDP]; !ok { case gortsplib.TransportUDP:
if _, ok := s.protocols[conf.Protocol(gortsplib.TransportUDP)]; !ok {
return &base.Response{ return &base.Response{
StatusCode: base.StatusUnsupportedTransport, StatusCode: base.StatusUnsupportedTransport,
}, nil, nil }, nil, nil
} }
if ctx.Transport.Delivery != nil && *ctx.Transport.Delivery == base.StreamDeliveryMulticast { case gortsplib.TransportUDPMulticast:
if _, ok := s.protocols[conf.ProtocolMulticast]; !ok { if _, ok := s.protocols[conf.Protocol(gortsplib.TransportUDPMulticast)]; !ok {
return &base.Response{ return &base.Response{
StatusCode: base.StatusUnsupportedTransport, StatusCode: base.StatusUnsupportedTransport,
}, nil, nil }, nil, nil
} }
default: // TCP
if _, ok := s.protocols[conf.Protocol(gortsplib.TransportTCP)]; !ok {
return &base.Response{
StatusCode: base.StatusUnsupportedTransport,
}, nil, nil
} }
} else if _, ok := s.protocols[conf.ProtocolTCP]; !ok {
return &base.Response{
StatusCode: base.StatusUnsupportedTransport,
}, nil, nil
} }
switch s.ss.State() { switch s.ss.State() {
@ -347,7 +343,7 @@ func (s *rtspSession) OnReaderAccepted() {
} }
return "tracks" return "tracks"
}(), }(),
s.displayedProtocol()) s.ss.SetuppedTransport())
} }
// OnReaderFrame implements reader. // OnReaderFrame implements reader.
@ -396,7 +392,7 @@ func (s *rtspSession) OnPublisherAccepted(tracksLen int) {
} }
return "tracks" return "tracks"
}(), }(),
s.displayedProtocol()) s.ss.SetuppedTransport())
} }
// OnFrame is called by rtspServer. // OnFrame is called by rtspServer.

2
internal/core/rtsp_source.go

@ -118,7 +118,7 @@ func (s *rtspSource) runInner() bool {
s.log(logger.Debug, "connecting") s.log(logger.Debug, "connecting")
client := &gortsplib.Client{ client := &gortsplib.Client{
Protocol: s.proto.ClientProtocol, Transport: s.proto.Transport,
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
VerifyConnection: func(cs tls.ConnectionState) error { VerifyConnection: func(cs tls.ConnectionState) error {

2
rtsp-simple-server.yml

@ -45,7 +45,7 @@ runOnConnectRestart: no
# disable support for the RTSP protocol. # disable support for the RTSP protocol.
rtspDisable: no rtspDisable: no
# supported RTSP stream protocols. # supported RTSP transport protocols.
# UDP is the most performant, but doesn't work when there's a NAT/firewall between # UDP is the most performant, but doesn't work when there's a NAT/firewall between
# server and clients, and doesn't support encryption. # server and clients, and doesn't support encryption.
# UDP-multicast allows to save bandwidth when clients are all in the same LAN. # UDP-multicast allows to save bandwidth when clients are all in the same LAN.

Loading…
Cancel
Save