add whepHandshakeTimeout, whepTrackGatherTimeout, whepSTUNGatherTimeout
This commit is contained in:
+10
-2
@@ -339,12 +339,12 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/WebRTCICEServer'
|
$ref: '#/components/schemas/WebRTCICEServer'
|
||||||
|
webrtcSTUNGatherTimeout:
|
||||||
|
type: string
|
||||||
webrtcHandshakeTimeout:
|
webrtcHandshakeTimeout:
|
||||||
type: string
|
type: string
|
||||||
webrtcTrackGatherTimeout:
|
webrtcTrackGatherTimeout:
|
||||||
type: string
|
type: string
|
||||||
webrtcSTUNGatherTimeout:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
# SRT server
|
# SRT server
|
||||||
srt:
|
srt:
|
||||||
@@ -430,6 +430,14 @@ components:
|
|||||||
rtpSDP:
|
rtpSDP:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
# WHEP source
|
||||||
|
whepSTUNGatherTimeout:
|
||||||
|
type: string
|
||||||
|
whepHandshakeTimeout:
|
||||||
|
type: string
|
||||||
|
whepTrackGatherTimeout:
|
||||||
|
type: string
|
||||||
|
|
||||||
# Redirect source
|
# Redirect source
|
||||||
sourceRedirect:
|
sourceRedirect:
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -380,9 +380,9 @@ type Conf struct {
|
|||||||
WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"`
|
WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"`
|
||||||
WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"`
|
WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"`
|
||||||
WebRTCICEServers2 []WebRTCICEServer `json:"webrtcICEServers2"`
|
WebRTCICEServers2 []WebRTCICEServer `json:"webrtcICEServers2"`
|
||||||
|
WebRTCSTUNGatherTimeout Duration `json:"webrtcSTUNGatherTimeout"`
|
||||||
WebRTCHandshakeTimeout Duration `json:"webrtcHandshakeTimeout"`
|
WebRTCHandshakeTimeout Duration `json:"webrtcHandshakeTimeout"`
|
||||||
WebRTCTrackGatherTimeout Duration `json:"webrtcTrackGatherTimeout"`
|
WebRTCTrackGatherTimeout Duration `json:"webrtcTrackGatherTimeout"`
|
||||||
WebRTCSTUNGatherTimeout Duration `json:"webrtcSTUNGatherTimeout"`
|
|
||||||
WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated
|
WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated
|
||||||
WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated
|
WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated
|
||||||
WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated
|
WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated
|
||||||
@@ -513,9 +513,9 @@ func (conf *Conf) setDefaults() {
|
|||||||
conf.WebRTCAllowOrigins = []string{"*"}
|
conf.WebRTCAllowOrigins = []string{"*"}
|
||||||
conf.WebRTCLocalUDPAddress = ":8189"
|
conf.WebRTCLocalUDPAddress = ":8189"
|
||||||
conf.WebRTCIPsFromInterfaces = true
|
conf.WebRTCIPsFromInterfaces = true
|
||||||
|
conf.WebRTCSTUNGatherTimeout = 5 * Duration(time.Second)
|
||||||
conf.WebRTCHandshakeTimeout = 10 * Duration(time.Second)
|
conf.WebRTCHandshakeTimeout = 10 * Duration(time.Second)
|
||||||
conf.WebRTCTrackGatherTimeout = 2 * Duration(time.Second)
|
conf.WebRTCTrackGatherTimeout = 2 * Duration(time.Second)
|
||||||
conf.WebRTCSTUNGatherTimeout = 5 * Duration(time.Second)
|
|
||||||
|
|
||||||
// SRT server
|
// SRT server
|
||||||
conf.SRT = true
|
conf.SRT = true
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ func TestConfFromFile(t *testing.T) {
|
|||||||
RecordSegmentDuration: 3600000000000,
|
RecordSegmentDuration: 3600000000000,
|
||||||
RecordDeleteAfter: 86400000000000,
|
RecordDeleteAfter: 86400000000000,
|
||||||
RTSPUDPSourcePortRange: []uint{10000, 65535},
|
RTSPUDPSourcePortRange: []uint{10000, 65535},
|
||||||
|
WHEPSTUNGatherTimeout: 5 * Duration(time.Second),
|
||||||
|
WHEPHandshakeTimeout: 10 * Duration(time.Second),
|
||||||
|
WHEPTrackGatherTimeout: 2 * Duration(time.Second),
|
||||||
RPICameraWidth: 1920,
|
RPICameraWidth: 1920,
|
||||||
RPICameraHeight: 1080,
|
RPICameraHeight: 1080,
|
||||||
RPICameraContrast: 1,
|
RPICameraContrast: 1,
|
||||||
|
|||||||
@@ -196,6 +196,11 @@ type Path struct {
|
|||||||
RTPSDP string `json:"rtpSDP"`
|
RTPSDP string `json:"rtpSDP"`
|
||||||
RTPUDPReadBufferSize *uint `json:"rtpUDPReadBufferSize,omitempty"` // deprecated
|
RTPUDPReadBufferSize *uint `json:"rtpUDPReadBufferSize,omitempty"` // deprecated
|
||||||
|
|
||||||
|
// WHEP source
|
||||||
|
WHEPSTUNGatherTimeout Duration `json:"whepSTUNGatherTimeout"`
|
||||||
|
WHEPHandshakeTimeout Duration `json:"whepHandshakeTimeout"`
|
||||||
|
WHEPTrackGatherTimeout Duration `json:"whepTrackGatherTimeout"`
|
||||||
|
|
||||||
// Redirect source
|
// Redirect source
|
||||||
SourceRedirect string `json:"sourceRedirect"`
|
SourceRedirect string `json:"sourceRedirect"`
|
||||||
|
|
||||||
@@ -291,6 +296,11 @@ func (pconf *Path) setDefaults() {
|
|||||||
// RTSP source
|
// RTSP source
|
||||||
pconf.RTSPUDPSourcePortRange = []uint{10000, 65535}
|
pconf.RTSPUDPSourcePortRange = []uint{10000, 65535}
|
||||||
|
|
||||||
|
// WHEP source
|
||||||
|
pconf.WHEPSTUNGatherTimeout = Duration(5 * time.Second)
|
||||||
|
pconf.WHEPHandshakeTimeout = Duration(10 * time.Second)
|
||||||
|
pconf.WHEPTrackGatherTimeout = Duration(2 * time.Second)
|
||||||
|
|
||||||
// Raspberry Pi Camera source
|
// Raspberry Pi Camera source
|
||||||
pconf.RPICameraWidth = 1920
|
pconf.RPICameraWidth = 1920
|
||||||
pconf.RPICameraHeight = 1080
|
pconf.RPICameraHeight = 1080
|
||||||
|
|||||||
+18
-18
@@ -364,24 +364,24 @@ func TestAPIProtocolListGet(t *testing.T) {
|
|||||||
"srt",
|
"srt",
|
||||||
} {
|
} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
conf := "api: yes\n"
|
cnf := "api: yes\n"
|
||||||
|
|
||||||
switch ca {
|
switch ca {
|
||||||
case "rtsps conns", "rtsps sessions":
|
case "rtsps conns", "rtsps sessions":
|
||||||
conf += "rtspEncryption: strict\n" +
|
cnf += "rtspEncryption: strict\n" +
|
||||||
"rtspServerCert: " + serverCertFpath + "\n" +
|
"rtspServerCert: " + serverCertFpath + "\n" +
|
||||||
"rtspServerKey: " + serverKeyFpath + "\n"
|
"rtspServerKey: " + serverKeyFpath + "\n"
|
||||||
|
|
||||||
case "rtmps":
|
case "rtmps":
|
||||||
conf += "rtmpEncryption: strict\n" +
|
cnf += "rtmpEncryption: strict\n" +
|
||||||
"rtmpServerCert: " + serverCertFpath + "\n" +
|
"rtmpServerCert: " + serverCertFpath + "\n" +
|
||||||
"rtmpServerKey: " + serverKeyFpath + "\n"
|
"rtmpServerKey: " + serverKeyFpath + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
conf += "paths:\n" +
|
cnf += "paths:\n" +
|
||||||
" all_others:\n"
|
" all_others:\n"
|
||||||
|
|
||||||
p, ok := newInstance(conf)
|
p, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
@@ -893,25 +893,25 @@ func TestAPIProtocolGetNotFound(t *testing.T) {
|
|||||||
"srt",
|
"srt",
|
||||||
} {
|
} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
conf := "api: yes\n"
|
cnf := "api: yes\n"
|
||||||
|
|
||||||
switch ca {
|
switch ca {
|
||||||
case "rtsps conns", "rtsps sessions":
|
case "rtsps conns", "rtsps sessions":
|
||||||
conf += "rtspTransports: [tcp]\n" +
|
cnf += "rtspTransports: [tcp]\n" +
|
||||||
"rtspEncryption: strict\n" +
|
"rtspEncryption: strict\n" +
|
||||||
"rtspServerCert: " + serverCertFpath + "\n" +
|
"rtspServerCert: " + serverCertFpath + "\n" +
|
||||||
"rtspServerKey: " + serverKeyFpath + "\n"
|
"rtspServerKey: " + serverKeyFpath + "\n"
|
||||||
|
|
||||||
case "rtmps":
|
case "rtmps":
|
||||||
conf += "rtmpEncryption: strict\n" +
|
cnf += "rtmpEncryption: strict\n" +
|
||||||
"rtmpServerCert: " + serverCertFpath + "\n" +
|
"rtmpServerCert: " + serverCertFpath + "\n" +
|
||||||
"rtmpServerKey: " + serverKeyFpath + "\n"
|
"rtmpServerKey: " + serverKeyFpath + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
conf += "paths:\n" +
|
cnf += "paths:\n" +
|
||||||
" all_others:\n"
|
" all_others:\n"
|
||||||
|
|
||||||
p, ok := newInstance(conf)
|
p, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
@@ -993,19 +993,19 @@ func TestAPIProtocolKick(t *testing.T) {
|
|||||||
"srt",
|
"srt",
|
||||||
} {
|
} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
conf := "api: yes\n"
|
cnf := "api: yes\n"
|
||||||
|
|
||||||
if ca == "rtsps" {
|
if ca == "rtsps" {
|
||||||
conf += "rtspTransports: [tcp]\n" +
|
cnf += "rtspTransports: [tcp]\n" +
|
||||||
"rtspEncryption: strict\n" +
|
"rtspEncryption: strict\n" +
|
||||||
"rtspServerCert: " + serverCertFpath + "\n" +
|
"rtspServerCert: " + serverCertFpath + "\n" +
|
||||||
"rtspServerKey: " + serverKeyFpath + "\n"
|
"rtspServerKey: " + serverKeyFpath + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
conf += "paths:\n" +
|
cnf += "paths:\n" +
|
||||||
" all_others:\n"
|
" all_others:\n"
|
||||||
|
|
||||||
p, ok := newInstance(conf)
|
p, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
@@ -1171,19 +1171,19 @@ func TestAPIProtocolKickNotFound(t *testing.T) {
|
|||||||
"srt",
|
"srt",
|
||||||
} {
|
} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
conf := "api: yes\n"
|
cnf := "api: yes\n"
|
||||||
|
|
||||||
if ca == "rtsps" {
|
if ca == "rtsps" {
|
||||||
conf += "rtspTransports: [tcp]\n" +
|
cnf += "rtspTransports: [tcp]\n" +
|
||||||
"rtspEncryption: strict\n" +
|
"rtspEncryption: strict\n" +
|
||||||
"rtspServerCert: " + serverCertFpath + "\n" +
|
"rtspServerCert: " + serverCertFpath + "\n" +
|
||||||
"rtspServerKey: " + serverKeyFpath + "\n"
|
"rtspServerKey: " + serverKeyFpath + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
conf += "paths:\n" +
|
cnf += "paths:\n" +
|
||||||
" all_others:\n"
|
" all_others:\n"
|
||||||
|
|
||||||
p, ok := newInstance(conf)
|
p, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
|
|||||||
@@ -627,8 +627,8 @@ func (p *Core) createResources(initial bool) error {
|
|||||||
IPsFromInterfacesList: p.conf.WebRTCIPsFromInterfacesList,
|
IPsFromInterfacesList: p.conf.WebRTCIPsFromInterfacesList,
|
||||||
AdditionalHosts: p.conf.WebRTCAdditionalHosts,
|
AdditionalHosts: p.conf.WebRTCAdditionalHosts,
|
||||||
ICEServers: p.conf.WebRTCICEServers2,
|
ICEServers: p.conf.WebRTCICEServers2,
|
||||||
HandshakeTimeout: p.conf.WebRTCHandshakeTimeout,
|
|
||||||
STUNGatherTimeout: p.conf.WebRTCSTUNGatherTimeout,
|
STUNGatherTimeout: p.conf.WebRTCSTUNGatherTimeout,
|
||||||
|
HandshakeTimeout: p.conf.WebRTCHandshakeTimeout,
|
||||||
TrackGatherTimeout: p.conf.WebRTCTrackGatherTimeout,
|
TrackGatherTimeout: p.conf.WebRTCTrackGatherTimeout,
|
||||||
ExternalCmdPool: p.externalCmdPool,
|
ExternalCmdPool: p.externalCmdPool,
|
||||||
Metrics: p.metrics,
|
Metrics: p.metrics,
|
||||||
@@ -911,8 +911,8 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
|
|||||||
!reflect.DeepEqual(newConf.WebRTCIPsFromInterfacesList, p.conf.WebRTCIPsFromInterfacesList) ||
|
!reflect.DeepEqual(newConf.WebRTCIPsFromInterfacesList, p.conf.WebRTCIPsFromInterfacesList) ||
|
||||||
!reflect.DeepEqual(newConf.WebRTCAdditionalHosts, p.conf.WebRTCAdditionalHosts) ||
|
!reflect.DeepEqual(newConf.WebRTCAdditionalHosts, p.conf.WebRTCAdditionalHosts) ||
|
||||||
!reflect.DeepEqual(newConf.WebRTCICEServers2, p.conf.WebRTCICEServers2) ||
|
!reflect.DeepEqual(newConf.WebRTCICEServers2, p.conf.WebRTCICEServers2) ||
|
||||||
newConf.WebRTCHandshakeTimeout != p.conf.WebRTCHandshakeTimeout ||
|
|
||||||
newConf.WebRTCSTUNGatherTimeout != p.conf.WebRTCSTUNGatherTimeout ||
|
newConf.WebRTCSTUNGatherTimeout != p.conf.WebRTCSTUNGatherTimeout ||
|
||||||
|
newConf.WebRTCHandshakeTimeout != p.conf.WebRTCHandshakeTimeout ||
|
||||||
newConf.WebRTCTrackGatherTimeout != p.conf.WebRTCTrackGatherTimeout ||
|
newConf.WebRTCTrackGatherTimeout != p.conf.WebRTCTrackGatherTimeout ||
|
||||||
closeMetrics ||
|
closeMetrics ||
|
||||||
closePathManager ||
|
closePathManager ||
|
||||||
|
|||||||
@@ -789,30 +789,30 @@ func TestPathFallback(t *testing.T) {
|
|||||||
"source",
|
"source",
|
||||||
} {
|
} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
var conf string
|
var cnf string
|
||||||
|
|
||||||
switch ca {
|
switch ca {
|
||||||
case "absolute":
|
case "absolute":
|
||||||
conf = "paths:\n" +
|
cnf = "paths:\n" +
|
||||||
" path1:\n" +
|
" path1:\n" +
|
||||||
" fallback: rtsp://localhost:8554/path2\n" +
|
" fallback: rtsp://localhost:8554/path2\n" +
|
||||||
" path2:\n"
|
" path2:\n"
|
||||||
|
|
||||||
case "relative":
|
case "relative":
|
||||||
conf = "paths:\n" +
|
cnf = "paths:\n" +
|
||||||
" path1:\n" +
|
" path1:\n" +
|
||||||
" fallback: /path2\n" +
|
" fallback: /path2\n" +
|
||||||
" path2:\n"
|
" path2:\n"
|
||||||
|
|
||||||
case "source":
|
case "source":
|
||||||
conf = "paths:\n" +
|
cnf = "paths:\n" +
|
||||||
" path1:\n" +
|
" path1:\n" +
|
||||||
" fallback: /path2\n" +
|
" fallback: /path2\n" +
|
||||||
" source: rtsp://localhost:3333/nonexistent\n" +
|
" source: rtsp://localhost:3333/nonexistent\n" +
|
||||||
" path2:\n"
|
" path2:\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
p1, ok := newInstance(conf)
|
p1, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p1.Close()
|
defer p1.Close()
|
||||||
|
|
||||||
@@ -911,15 +911,15 @@ func TestPathOverridePublisher(t *testing.T) {
|
|||||||
"disabled",
|
"disabled",
|
||||||
} {
|
} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
conf := "rtmp: no\n" +
|
cnf := "rtmp: no\n" +
|
||||||
"paths:\n" +
|
"paths:\n" +
|
||||||
" all_others:\n"
|
" all_others:\n"
|
||||||
|
|
||||||
if ca == "disabled" {
|
if ca == "disabled" {
|
||||||
conf += " overridePublisher: no\n"
|
cnf += " overridePublisher: no\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
p, ok := newInstance(conf)
|
p, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
|
||||||
"github.com/bluenviron/mediamtx/internal/logger"
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
"github.com/bluenviron/mediamtx/internal/stream"
|
"github.com/bluenviron/mediamtx/internal/stream"
|
||||||
"github.com/bluenviron/mediamtx/internal/test"
|
"github.com/bluenviron/mediamtx/internal/test"
|
||||||
@@ -112,24 +111,20 @@ func TestFromStreamResampleOpus(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pc1 := &PeerConnection{
|
pc1 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: false,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
Publish: false,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err = pc1.Start()
|
err = pc1.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer pc1.Close()
|
defer pc1.Close()
|
||||||
|
|
||||||
pc2 := &PeerConnection{
|
pc2 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: true,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
Publish: true,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r := &stream.Reader{Parent: nil}
|
r := &stream.Reader{Parent: nil}
|
||||||
@@ -150,10 +145,10 @@ func TestFromStreamResampleOpus(t *testing.T) {
|
|||||||
err = pc1.SetAnswer(answer)
|
err = pc1.SetAnswer(answer)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc1.WaitUntilConnected()
|
err = pc1.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc2.WaitUntilConnected()
|
err = pc2.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
strm.AddReader(r)
|
strm.AddReader(r)
|
||||||
@@ -191,7 +186,7 @@ func TestFromStreamResampleOpus(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
|
|
||||||
err = pc1.GatherIncomingTracks()
|
err = pc1.GatherIncomingTracks(2 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := pc1.IncomingTracks()
|
tracks := pc1.IncomingTracks()
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/pion/sdp/v3"
|
"github.com/pion/sdp/v3"
|
||||||
"github.com/pion/webrtc/v4"
|
"github.com/pion/webrtc/v4"
|
||||||
|
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
|
||||||
"github.com/bluenviron/mediamtx/internal/logger"
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -140,9 +139,7 @@ type PeerConnection struct {
|
|||||||
IPsFromInterfaces bool
|
IPsFromInterfaces bool
|
||||||
IPsFromInterfacesList []string
|
IPsFromInterfacesList []string
|
||||||
AdditionalHosts []string
|
AdditionalHosts []string
|
||||||
HandshakeTimeout conf.Duration
|
STUNGatherTimeout time.Duration
|
||||||
TrackGatherTimeout conf.Duration
|
|
||||||
STUNGatherTimeout conf.Duration
|
|
||||||
Publish bool
|
Publish bool
|
||||||
OutgoingTracks []*OutgoingTrack
|
OutgoingTracks []*OutgoingTrack
|
||||||
OutgoingDataChannels []*OutgoingDataChannel
|
OutgoingDataChannels []*OutgoingDataChannel
|
||||||
@@ -167,6 +164,10 @@ type PeerConnection struct {
|
|||||||
|
|
||||||
// Start starts the peer connection.
|
// Start starts the peer connection.
|
||||||
func (co *PeerConnection) Start() error {
|
func (co *PeerConnection) Start() error {
|
||||||
|
if co.STUNGatherTimeout == 0 {
|
||||||
|
co.STUNGatherTimeout = 5 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
settingsEngine := webrtc.SettingEngine{}
|
settingsEngine := webrtc.SettingEngine{}
|
||||||
|
|
||||||
settingsEngine.SetIncludeLoopbackCandidate(true)
|
settingsEngine.SetIncludeLoopbackCandidate(true)
|
||||||
@@ -191,7 +192,7 @@ func (co *PeerConnection) Start() error {
|
|||||||
settingsEngine.SetICETCPMux(co.ICETCPMux.Mux)
|
settingsEngine.SetICETCPMux(co.ICETCPMux.Mux)
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsEngine.SetSTUNGatherTimeout(time.Duration(co.STUNGatherTimeout))
|
settingsEngine.SetSTUNGatherTimeout(co.STUNGatherTimeout)
|
||||||
|
|
||||||
webrtcNet := &webrtcNet{
|
webrtcNet := &webrtcNet{
|
||||||
udpReadBufferSize: int(co.UDPReadBufferSize),
|
udpReadBufferSize: int(co.UDPReadBufferSize),
|
||||||
@@ -669,8 +670,8 @@ func (co *PeerConnection) waitGatheringDone() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WaitUntilConnected waits until connection is established.
|
// WaitUntilConnected waits until connection is established.
|
||||||
func (co *PeerConnection) WaitUntilConnected() error {
|
func (co *PeerConnection) WaitUntilConnected(timeout time.Duration) error {
|
||||||
t := time.NewTimer(time.Duration(co.HandshakeTimeout))
|
t := time.NewTimer(timeout)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
@@ -691,13 +692,13 @@ outer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GatherIncomingTracks gathers incoming tracks.
|
// GatherIncomingTracks gathers incoming tracks.
|
||||||
func (co *PeerConnection) GatherIncomingTracks() error {
|
func (co *PeerConnection) GatherIncomingTracks(timeout time.Duration) error {
|
||||||
var sdp sdp.SessionDescription
|
var sdp sdp.SessionDescription
|
||||||
sdp.Unmarshal([]byte(co.wr.RemoteDescription().SDP)) //nolint:errcheck
|
sdp.Unmarshal([]byte(co.wr.RemoteDescription().SDP)) //nolint:errcheck
|
||||||
|
|
||||||
maxTrackCount := len(sdp.MediaDescriptions)
|
maxTrackCount := len(sdp.MediaDescriptions)
|
||||||
|
|
||||||
t := time.NewTimer(time.Duration(co.TrackGatherTimeout))
|
t := time.NewTimer(timeout)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
|
||||||
"github.com/bluenviron/mediamtx/internal/test"
|
"github.com/bluenviron/mediamtx/internal/test"
|
||||||
"github.com/pion/ice/v4"
|
"github.com/pion/ice/v4"
|
||||||
"github.com/pion/logging"
|
"github.com/pion/logging"
|
||||||
@@ -37,13 +36,10 @@ func gatherCodecs(tracks []*IncomingTrack) []webrtc.RTPCodecParameters {
|
|||||||
|
|
||||||
func TestPeerConnectionCloseImmediately(t *testing.T) {
|
func TestPeerConnectionCloseImmediately(t *testing.T) {
|
||||||
pc := &PeerConnection{
|
pc := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: false,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
Publish: false,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err := pc.Start()
|
err := pc.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -115,8 +111,6 @@ func TestPeerConnectionCandidates(t *testing.T) {
|
|||||||
ICETCPMux: tcpMux,
|
ICETCPMux: tcpMux,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
IPsFromInterfacesList: []string{"lo"},
|
IPsFromInterfacesList: []string{"lo"},
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
Log: test.NilLogger,
|
Log: test.NilLogger,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,8 +182,6 @@ func TestPeerConnectionConnectivity(t *testing.T) {
|
|||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
IPsFromInterfacesList: []string{"lo"},
|
IPsFromInterfacesList: []string{"lo"},
|
||||||
ICEServers: iceServers,
|
ICEServers: iceServers,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
Log: test.NilLogger,
|
Log: test.NilLogger,
|
||||||
}
|
}
|
||||||
err := clientPC.Start()
|
err := clientPC.Start()
|
||||||
@@ -219,13 +211,11 @@ func TestPeerConnectionConnectivity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serverPC := &PeerConnection{
|
serverPC := &PeerConnection{
|
||||||
LocalRandomUDP: (mode == "active udp"),
|
LocalRandomUDP: (mode == "active udp"),
|
||||||
ICEUDPMux: udpMux,
|
ICEUDPMux: udpMux,
|
||||||
ICETCPMux: tcpMux,
|
ICETCPMux: tcpMux,
|
||||||
ICEServers: iceServers,
|
ICEServers: iceServers,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: true,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
Publish: true,
|
|
||||||
OutgoingTracks: []*OutgoingTrack{{
|
OutgoingTracks: []*OutgoingTrack{{
|
||||||
Caps: webrtc.RTPCodecCapability{
|
Caps: webrtc.RTPCodecCapability{
|
||||||
MimeType: webrtc.MimeTypeAV1,
|
MimeType: webrtc.MimeTypeAV1,
|
||||||
@@ -270,7 +260,7 @@ func TestPeerConnectionConnectivity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = serverPC.WaitUntilConnected()
|
err = serverPC.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -307,12 +297,10 @@ func TestPeerConnectionRead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
reader := &PeerConnection{
|
reader := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: false,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
Publish: false,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err = reader.Start()
|
err = reader.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -330,7 +318,7 @@ func TestPeerConnectionRead(t *testing.T) {
|
|||||||
err = pub.SetRemoteDescription(*answer)
|
err = pub.SetRemoteDescription(*answer)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = reader.WaitUntilConnected()
|
err = reader.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -363,7 +351,7 @@ func TestPeerConnectionRead(t *testing.T) {
|
|||||||
require.NoError(t, err2)
|
require.NoError(t, err2)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = reader.GatherIncomingTracks()
|
err = reader.GatherIncomingTracks(2 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
codecs := gatherCodecs(reader.IncomingTracks())
|
codecs := gatherCodecs(reader.IncomingTracks())
|
||||||
@@ -428,23 +416,19 @@ func TestPeerConnectionRead(t *testing.T) {
|
|||||||
|
|
||||||
func TestPeerConnectionPublishRead(t *testing.T) {
|
func TestPeerConnectionPublishRead(t *testing.T) {
|
||||||
pc1 := &PeerConnection{
|
pc1 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: false,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
Publish: false,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err := pc1.Start()
|
err := pc1.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer pc1.Close()
|
defer pc1.Close()
|
||||||
|
|
||||||
pc2 := &PeerConnection{
|
pc2 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: true,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
Publish: true,
|
|
||||||
OutgoingTracks: []*OutgoingTrack{
|
OutgoingTracks: []*OutgoingTrack{
|
||||||
{
|
{
|
||||||
Caps: webrtc.RTPCodecCapability{
|
Caps: webrtc.RTPCodecCapability{
|
||||||
@@ -475,10 +459,10 @@ func TestPeerConnectionPublishRead(t *testing.T) {
|
|||||||
err = pc1.SetAnswer(answer)
|
err = pc1.SetAnswer(answer)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc1.WaitUntilConnected()
|
err = pc1.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc2.WaitUntilConnected()
|
err = pc2.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, track := range pc2.OutgoingTracks {
|
for _, track := range pc2.OutgoingTracks {
|
||||||
@@ -496,7 +480,7 @@ func TestPeerConnectionPublishRead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pc1.GatherIncomingTracks()
|
err = pc1.GatherIncomingTracks(2 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
codecs := gatherCodecs(pc1.IncomingTracks())
|
codecs := gatherCodecs(pc1.IncomingTracks())
|
||||||
@@ -531,23 +515,19 @@ func TestPeerConnectionPublishRead(t *testing.T) {
|
|||||||
// test that an audio codec is present regardless of the fact that an audio track is.
|
// test that an audio codec is present regardless of the fact that an audio track is.
|
||||||
func TestPeerConnectionFallbackCodecs(t *testing.T) {
|
func TestPeerConnectionFallbackCodecs(t *testing.T) {
|
||||||
pc1 := &PeerConnection{
|
pc1 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: false,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
Publish: false,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err := pc1.Start()
|
err := pc1.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer pc1.Close()
|
defer pc1.Close()
|
||||||
|
|
||||||
pc2 := &PeerConnection{
|
pc2 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: true,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
Publish: true,
|
|
||||||
OutgoingTracks: []*OutgoingTrack{{
|
OutgoingTracks: []*OutgoingTrack{{
|
||||||
Caps: webrtc.RTPCodecCapability{
|
Caps: webrtc.RTPCodecCapability{
|
||||||
MimeType: webrtc.MimeTypeAV1,
|
MimeType: webrtc.MimeTypeAV1,
|
||||||
@@ -621,12 +601,9 @@ func TestPeerConnectionPublishDataChannel(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pc2 := &PeerConnection{
|
pc2 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: true,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
Publish: true,
|
|
||||||
OutgoingDataChannels: []*OutgoingDataChannel{
|
OutgoingDataChannels: []*OutgoingDataChannel{
|
||||||
{
|
{
|
||||||
Label: "test-channel",
|
Label: "test-channel",
|
||||||
@@ -644,7 +621,7 @@ func TestPeerConnectionPublishDataChannel(t *testing.T) {
|
|||||||
err = pc1.SetRemoteDescription(*answer)
|
err = pc1.SetRemoteDescription(*answer)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc2.WaitUntilConnected()
|
err = pc2.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
<-dataChanCreated
|
<-dataChanCreated
|
||||||
|
|||||||
@@ -335,11 +335,9 @@ func TestToStream(t *testing.T) {
|
|||||||
for _, ca := range toFromStreamCases {
|
for _, ca := range toFromStreamCases {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
pc1 := &PeerConnection{
|
pc1 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: true,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
Publish: true,
|
|
||||||
OutgoingTracks: []*OutgoingTrack{{
|
OutgoingTracks: []*OutgoingTrack{{
|
||||||
Caps: ca.webrtcCaps,
|
Caps: ca.webrtcCaps,
|
||||||
}},
|
}},
|
||||||
@@ -350,12 +348,10 @@ func TestToStream(t *testing.T) {
|
|||||||
defer pc1.Close()
|
defer pc1.Close()
|
||||||
|
|
||||||
pc2 := &PeerConnection{
|
pc2 := &PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: false,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
Publish: false,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err = pc2.Start()
|
err = pc2.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -383,10 +379,10 @@ func TestToStream(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = pc1.WaitUntilConnected()
|
err = pc1.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc2.WaitUntilConnected()
|
err = pc2.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc1.OutgoingTracks[0].WriteRTP(&rtp.Packet{
|
err = pc1.OutgoingTracks[0].WriteRTP(&rtp.Packet{
|
||||||
@@ -402,7 +398,7 @@ func TestToStream(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = pc2.GatherIncomingTracks()
|
err = pc2.GatherIncomingTracks(2 * time.Second)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var subStream *stream.SubStream
|
var subStream *stream.SubStream
|
||||||
|
|||||||
@@ -13,25 +13,22 @@ import (
|
|||||||
"github.com/pion/sdp/v3"
|
"github.com/pion/sdp/v3"
|
||||||
pwebrtc "github.com/pion/webrtc/v4"
|
pwebrtc "github.com/pion/webrtc/v4"
|
||||||
|
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
|
||||||
"github.com/bluenviron/mediamtx/internal/logger"
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
handshakeTimeout = 10 * time.Second
|
|
||||||
trackGatherTimeout = 2 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client is a WHIP client.
|
// Client is a WHIP client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
Publish bool
|
Publish bool
|
||||||
OutgoingTracks []*webrtc.OutgoingTrack
|
OutgoingTracks []*webrtc.OutgoingTrack
|
||||||
HTTPClient *http.Client
|
HTTPClient *http.Client
|
||||||
UDPReadBufferSize uint
|
UDPReadBufferSize uint
|
||||||
Log logger.Writer
|
STUNGatherTimeout time.Duration
|
||||||
|
HandshakeTimeout time.Duration
|
||||||
|
TrackGatherTimeout time.Duration
|
||||||
|
Log logger.Writer
|
||||||
|
|
||||||
pc *webrtc.PeerConnection
|
pc *webrtc.PeerConnection
|
||||||
patchIsSupported bool
|
patchIsSupported bool
|
||||||
@@ -39,21 +36,30 @@ type Client struct {
|
|||||||
|
|
||||||
// Initialize initializes the Client.
|
// Initialize initializes the Client.
|
||||||
func (c *Client) Initialize(ctx context.Context) error {
|
func (c *Client) Initialize(ctx context.Context) error {
|
||||||
|
if c.STUNGatherTimeout == 0 {
|
||||||
|
c.STUNGatherTimeout = 5 * time.Second
|
||||||
|
}
|
||||||
|
if c.HandshakeTimeout == 0 {
|
||||||
|
c.HandshakeTimeout = 10 * time.Second
|
||||||
|
}
|
||||||
|
if c.TrackGatherTimeout == 0 {
|
||||||
|
c.TrackGatherTimeout = 2 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
iceServers, err := c.optionsICEServers(ctx)
|
iceServers, err := c.optionsICEServers(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.pc = &webrtc.PeerConnection{
|
c.pc = &webrtc.PeerConnection{
|
||||||
UDPReadBufferSize: c.UDPReadBufferSize,
|
UDPReadBufferSize: c.UDPReadBufferSize,
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
ICEServers: iceServers,
|
ICEServers: iceServers,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Publish: c.Publish,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
STUNGatherTimeout: c.STUNGatherTimeout,
|
||||||
Publish: c.Publish,
|
OutgoingTracks: c.OutgoingTracks,
|
||||||
OutgoingTracks: c.OutgoingTracks,
|
Log: c.Log,
|
||||||
Log: c.Log,
|
|
||||||
}
|
}
|
||||||
err = c.pc.Start()
|
err = c.pc.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -120,7 +126,7 @@ func (c *Client) initializeInner(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
t := time.NewTimer(handshakeTimeout)
|
t := time.NewTimer(c.HandshakeTimeout)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
@@ -145,7 +151,7 @@ outer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !c.Publish {
|
if !c.Publish {
|
||||||
err = c.pc.GatherIncomingTracks()
|
err = c.pc.GatherIncomingTracks(c.TrackGatherTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.deleteSession(context.Background()) //nolint:errcheck
|
c.deleteSession(context.Background()) //nolint:errcheck
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
||||||
"github.com/bluenviron/mediamtx/internal/test"
|
"github.com/bluenviron/mediamtx/internal/test"
|
||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
@@ -70,14 +69,11 @@ func TestClientRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pc := &webrtc.PeerConnection{
|
pc := &webrtc.PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
Publish: true,
|
Publish: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
OutgoingTracks: outgoingTracks,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
OutgoingTracks: outgoingTracks,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err := pc.Start()
|
err := pc.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -116,7 +112,7 @@ func TestClientRead(t *testing.T) {
|
|||||||
w.Write([]byte(answer.SDP))
|
w.Write([]byte(answer.SDP))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err3 := pc.WaitUntilConnected()
|
err3 := pc.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err3)
|
require.NoError(t, err3)
|
||||||
|
|
||||||
for _, track := range outgoingTracks {
|
for _, track := range outgoingTracks {
|
||||||
@@ -243,12 +239,9 @@ func TestClientPublish(t *testing.T) {
|
|||||||
for _, ca := range []string{"audio", "video+audio"} {
|
for _, ca := range []string{"audio", "video+audio"} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
pc := &webrtc.PeerConnection{
|
pc := &webrtc.PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
Log: test.NilLogger,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err := pc.Start()
|
err := pc.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -288,10 +281,10 @@ func TestClientPublish(t *testing.T) {
|
|||||||
w.Write([]byte(answer.SDP))
|
w.Write([]byte(answer.SDP))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err3 := pc.WaitUntilConnected()
|
err3 := pc.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err3)
|
require.NoError(t, err3)
|
||||||
|
|
||||||
err3 = pc.GatherIncomingTracks()
|
err3 = pc.GatherIncomingTracks(2 * time.Second)
|
||||||
require.NoError(t, err3)
|
require.NoError(t, err3)
|
||||||
|
|
||||||
codecs := gatherCodecs(pc.IncomingTracks())
|
codecs := gatherCodecs(pc.IncomingTracks())
|
||||||
|
|||||||
@@ -201,9 +201,9 @@ type Server struct {
|
|||||||
IPsFromInterfacesList []string
|
IPsFromInterfacesList []string
|
||||||
AdditionalHosts []string
|
AdditionalHosts []string
|
||||||
ICEServers []conf.WebRTCICEServer
|
ICEServers []conf.WebRTCICEServer
|
||||||
|
STUNGatherTimeout conf.Duration
|
||||||
HandshakeTimeout conf.Duration
|
HandshakeTimeout conf.Duration
|
||||||
TrackGatherTimeout conf.Duration
|
TrackGatherTimeout conf.Duration
|
||||||
STUNGatherTimeout conf.Duration
|
|
||||||
ExternalCmdPool *externalcmd.Pool
|
ExternalCmdPool *externalcmd.Pool
|
||||||
Metrics serverMetrics
|
Metrics serverMetrics
|
||||||
PathManager serverPathManager
|
PathManager serverPathManager
|
||||||
@@ -357,9 +357,9 @@ outer:
|
|||||||
additionalHosts: s.AdditionalHosts,
|
additionalHosts: s.AdditionalHosts,
|
||||||
iceUDPMux: s.iceUDPMux,
|
iceUDPMux: s.iceUDPMux,
|
||||||
iceTCPMux: s.iceTCPMux,
|
iceTCPMux: s.iceTCPMux,
|
||||||
|
stunGatherTimeout: s.STUNGatherTimeout,
|
||||||
handshakeTimeout: s.HandshakeTimeout,
|
handshakeTimeout: s.HandshakeTimeout,
|
||||||
trackGatherTimeout: s.TrackGatherTimeout,
|
trackGatherTimeout: s.TrackGatherTimeout,
|
||||||
stunGatherTimeout: s.STUNGatherTimeout,
|
|
||||||
req: req,
|
req: req,
|
||||||
wg: &wg,
|
wg: &wg,
|
||||||
externalCmdPool: s.ExternalCmdPool,
|
externalCmdPool: s.ExternalCmdPool,
|
||||||
|
|||||||
@@ -161,9 +161,9 @@ func TestServerOptionsICEServer(t *testing.T) {
|
|||||||
Username: "myuser",
|
Username: "myuser",
|
||||||
Password: "mypass",
|
Password: "mypass",
|
||||||
}},
|
}},
|
||||||
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
PathManager: pathManager,
|
PathManager: pathManager,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -267,9 +267,9 @@ func TestServerPublish(t *testing.T) {
|
|||||||
IPsFromInterfacesList: []string{},
|
IPsFromInterfacesList: []string{},
|
||||||
AdditionalHosts: []string{},
|
AdditionalHosts: []string{},
|
||||||
ICEServers: []conf.WebRTCICEServer{},
|
ICEServers: []conf.WebRTCICEServer{},
|
||||||
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
PathManager: pathManager,
|
PathManager: pathManager,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -514,9 +514,9 @@ func TestServerRead(t *testing.T) {
|
|||||||
IPsFromInterfacesList: []string{},
|
IPsFromInterfacesList: []string{},
|
||||||
AdditionalHosts: []string{},
|
AdditionalHosts: []string{},
|
||||||
ICEServers: []conf.WebRTCICEServer{},
|
ICEServers: []conf.WebRTCICEServer{},
|
||||||
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
PathManager: pathManager,
|
PathManager: pathManager,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -603,9 +603,9 @@ func TestServerReadNotFound(t *testing.T) {
|
|||||||
IPsFromInterfacesList: []string{},
|
IPsFromInterfacesList: []string{},
|
||||||
AdditionalHosts: []string{},
|
AdditionalHosts: []string{},
|
||||||
ICEServers: []conf.WebRTCICEServer{},
|
ICEServers: []conf.WebRTCICEServer{},
|
||||||
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
PathManager: pm,
|
PathManager: pm,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ type session struct {
|
|||||||
additionalHosts []string
|
additionalHosts []string
|
||||||
iceUDPMux ice.UDPMux
|
iceUDPMux ice.UDPMux
|
||||||
iceTCPMux *webrtc.TCPMuxWrapper
|
iceTCPMux *webrtc.TCPMuxWrapper
|
||||||
|
stunGatherTimeout conf.Duration
|
||||||
handshakeTimeout conf.Duration
|
handshakeTimeout conf.Duration
|
||||||
trackGatherTimeout conf.Duration
|
trackGatherTimeout conf.Duration
|
||||||
stunGatherTimeout conf.Duration
|
|
||||||
req webRTCNewSessionReq
|
req webRTCNewSessionReq
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
externalCmdPool *externalcmd.Pool
|
externalCmdPool *externalcmd.Pool
|
||||||
@@ -166,9 +166,7 @@ func (s *session) runPublish() (int, error) {
|
|||||||
IPsFromInterfaces: s.ipsFromInterfaces,
|
IPsFromInterfaces: s.ipsFromInterfaces,
|
||||||
IPsFromInterfacesList: s.ipsFromInterfacesList,
|
IPsFromInterfacesList: s.ipsFromInterfacesList,
|
||||||
AdditionalHosts: s.additionalHosts,
|
AdditionalHosts: s.additionalHosts,
|
||||||
HandshakeTimeout: s.handshakeTimeout,
|
STUNGatherTimeout: time.Duration(s.stunGatherTimeout),
|
||||||
TrackGatherTimeout: s.trackGatherTimeout,
|
|
||||||
STUNGatherTimeout: s.stunGatherTimeout,
|
|
||||||
Publish: false,
|
Publish: false,
|
||||||
Log: s,
|
Log: s,
|
||||||
}
|
}
|
||||||
@@ -219,7 +217,7 @@ func (s *session) runPublish() (int, error) {
|
|||||||
|
|
||||||
go s.readRemoteCandidates(pc)
|
go s.readRemoteCandidates(pc)
|
||||||
|
|
||||||
err = pc.WaitUntilConnected()
|
err = pc.WaitUntilConnected(time.Duration(s.handshakeTimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -228,7 +226,7 @@ func (s *session) runPublish() (int, error) {
|
|||||||
s.pc = pc
|
s.pc = pc
|
||||||
s.mutex.Unlock()
|
s.mutex.Unlock()
|
||||||
|
|
||||||
err = pc.GatherIncomingTracks()
|
err = pc.GatherIncomingTracks(time.Duration(s.trackGatherTimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -311,9 +309,7 @@ func (s *session) runRead() (int, error) {
|
|||||||
IPsFromInterfaces: s.ipsFromInterfaces,
|
IPsFromInterfaces: s.ipsFromInterfaces,
|
||||||
IPsFromInterfacesList: s.ipsFromInterfacesList,
|
IPsFromInterfacesList: s.ipsFromInterfacesList,
|
||||||
AdditionalHosts: s.additionalHosts,
|
AdditionalHosts: s.additionalHosts,
|
||||||
HandshakeTimeout: s.handshakeTimeout,
|
STUNGatherTimeout: time.Duration(s.stunGatherTimeout),
|
||||||
TrackGatherTimeout: s.trackGatherTimeout,
|
|
||||||
STUNGatherTimeout: s.stunGatherTimeout,
|
|
||||||
Publish: true,
|
Publish: true,
|
||||||
Log: s,
|
Log: s,
|
||||||
}
|
}
|
||||||
@@ -356,7 +352,7 @@ func (s *session) runRead() (int, error) {
|
|||||||
|
|
||||||
go s.readRemoteCandidates(pc)
|
go s.readRemoteCandidates(pc)
|
||||||
|
|
||||||
err = pc.WaitUntilConnected()
|
err = pc.WaitUntilConnected(time.Duration(s.handshakeTimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,8 +59,11 @@ func (s *Source) Run(params defs.StaticSourceRunParams) error {
|
|||||||
Timeout: time.Duration(s.ReadTimeout),
|
Timeout: time.Duration(s.ReadTimeout),
|
||||||
Transport: tr,
|
Transport: tr,
|
||||||
},
|
},
|
||||||
UDPReadBufferSize: s.UDPReadBufferSize,
|
UDPReadBufferSize: s.UDPReadBufferSize,
|
||||||
Log: s,
|
STUNGatherTimeout: time.Duration(params.Conf.WHEPSTUNGatherTimeout),
|
||||||
|
HandshakeTimeout: time.Duration(params.Conf.WHEPHandshakeTimeout),
|
||||||
|
TrackGatherTimeout: time.Duration(params.Conf.WHEPTrackGatherTimeout),
|
||||||
|
Log: s,
|
||||||
}
|
}
|
||||||
err = client.Initialize(params.Context)
|
err = client.Initialize(params.Context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -36,14 +36,11 @@ func TestSource(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
pc := &webrtc.PeerConnection{
|
pc := &webrtc.PeerConnection{
|
||||||
LocalRandomUDP: true,
|
LocalRandomUDP: true,
|
||||||
IPsFromInterfaces: true,
|
IPsFromInterfaces: true,
|
||||||
Publish: true,
|
Publish: true,
|
||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
OutgoingTracks: outgoingTracks,
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
Log: test.NilLogger,
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
|
||||||
OutgoingTracks: outgoingTracks,
|
|
||||||
Log: test.NilLogger,
|
|
||||||
}
|
}
|
||||||
err := pc.Start()
|
err := pc.Start()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -82,7 +79,7 @@ func TestSource(t *testing.T) {
|
|||||||
w.Write([]byte(answer.SDP))
|
w.Write([]byte(answer.SDP))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err3 := pc.WaitUntilConnected()
|
err3 := pc.WaitUntilConnected(10 * time.Second)
|
||||||
require.NoError(t, err3)
|
require.NoError(t, err3)
|
||||||
|
|
||||||
err3 = outgoingTracks[0].WriteRTP(&rtp.Packet{
|
err3 = outgoingTracks[0].WriteRTP(&rtp.Packet{
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ func TestHLSServerAuth(t *testing.T) {
|
|||||||
"fail",
|
"fail",
|
||||||
} {
|
} {
|
||||||
t.Run(result, func(t *testing.T) {
|
t.Run(result, func(t *testing.T) {
|
||||||
conf := "paths:\n" +
|
cnf := "paths:\n" +
|
||||||
" all_others:\n" +
|
" all_others:\n" +
|
||||||
" readUser: testreader\n" +
|
" readUser: testreader\n" +
|
||||||
" readPass: testpass\n" +
|
" readPass: testpass\n" +
|
||||||
" readIPs: [127.0.0.0/16]\n"
|
" readIPs: [127.0.0.0/16]\n"
|
||||||
|
|
||||||
p, ok := newInstance(conf)
|
p, ok := newInstance(cnf)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
|
|||||||
+15
-5
@@ -417,12 +417,12 @@ webrtcICEServers2: []
|
|||||||
# username: ''
|
# username: ''
|
||||||
# password: ''
|
# password: ''
|
||||||
# clientOnly: false
|
# clientOnly: false
|
||||||
|
# Maximum time to gather STUN candidates.
|
||||||
|
webrtcSTUNGatherTimeout: 5s
|
||||||
# Time to wait for the WebRTC handshake to complete.
|
# Time to wait for the WebRTC handshake to complete.
|
||||||
webrtcHandshakeTimeout: 10s
|
webrtcHandshakeTimeout: 10s
|
||||||
# Maximum time to gather video tracks.
|
# Maximum time to gather tracks.
|
||||||
webrtcTrackGatherTimeout: 2s
|
webrtcTrackGatherTimeout: 2s
|
||||||
# The maximum time to gather STUN candidates.
|
|
||||||
webrtcSTUNGatherTimeout: 5s
|
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# Global settings -> SRT server
|
# Global settings -> SRT server
|
||||||
@@ -458,8 +458,8 @@ pathDefaults:
|
|||||||
# * unix+mpegts://socket -> the stream is pulled from MPEG-TS over Unix socket, by using the socket
|
# * unix+mpegts://socket -> the stream is pulled from MPEG-TS over Unix socket, by using the socket
|
||||||
# * udp+rtp://ip:port -> the stream is pulled from RTP over UDP, by listening on the specified address
|
# * udp+rtp://ip:port -> the stream is pulled from RTP over UDP, by listening on the specified address
|
||||||
# * srt://existing-url -> the stream is pulled from another SRT server / camera
|
# * srt://existing-url -> the stream is pulled from another SRT server / camera
|
||||||
# * whep://existing-url -> the stream is pulled from another WebRTC server / camera
|
# * whep://existing-url -> the stream is pulled from another WebRTC server / camera with HTTP+WHEP
|
||||||
# * wheps://existing-url -> the stream is pulled from another WebRTC server / camera with HTTPS
|
# * wheps://existing-url -> the stream is pulled from another WebRTC server / camera with HTTPS+WHEP
|
||||||
# * redirect -> the stream is provided by another path or server
|
# * redirect -> the stream is provided by another path or server
|
||||||
# * rpiCamera -> the stream is provided by a Raspberry Pi Camera
|
# * rpiCamera -> the stream is provided by a Raspberry Pi Camera
|
||||||
# The following variables can be used in the source string:
|
# The following variables can be used in the source string:
|
||||||
@@ -568,6 +568,16 @@ pathDefaults:
|
|||||||
# session description protocol (SDP) of the RTP stream.
|
# session description protocol (SDP) of the RTP stream.
|
||||||
rtpSDP:
|
rtpSDP:
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Default path settings -> WebRTC / WHEP source (when source is WHEP)
|
||||||
|
|
||||||
|
# Maximum time to gather STUN candidates.
|
||||||
|
whepSTUNGatherTimeout: 5s
|
||||||
|
# Time to wait for the WebRTC handshake to complete.
|
||||||
|
whepHandshakeTimeout: 10s
|
||||||
|
# Maximum time to gather tracks.
|
||||||
|
whepTrackGatherTimeout: 2s
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# Default path settings -> Redirect source (when source is "redirect")
|
# Default path settings -> Redirect source (when source is "redirect")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user