mirror of
https://github.com/aler9/gortsplib
synced 2025-10-04 23:02:45 +08:00
65
client.go
65
client.go
@@ -245,6 +245,8 @@ type Client struct {
|
||||
UserAgent string
|
||||
// disable automatic RTCP sender reports.
|
||||
DisableRTCPSenderReports bool
|
||||
// explicitly request back channels to the server.
|
||||
RequestBackChannels bool
|
||||
// pointer to a variable that stores received bytes.
|
||||
BytesReceived *uint64
|
||||
// pointer to a variable that stores sent bytes.
|
||||
@@ -301,6 +303,8 @@ type Client struct {
|
||||
lastDescribeURL *base.URL
|
||||
baseURL *base.URL
|
||||
effectiveTransport *Transport
|
||||
backChannelSetupped bool
|
||||
stdChannelSetupped bool
|
||||
medias map[*description.Media]*clientMedia
|
||||
tcpCallbackByChannel map[int]readFunc
|
||||
lastRange *headers.Range
|
||||
@@ -662,9 +666,16 @@ func (c *Client) doClose() {
|
||||
}
|
||||
|
||||
if c.nconn != nil && c.baseURL != nil {
|
||||
header := base.Header{}
|
||||
|
||||
if c.backChannelSetupped {
|
||||
header["Require"] = base.HeaderValue{"www.onvif.org/ver20/backchannel"}
|
||||
}
|
||||
|
||||
c.do(&base.Request{ //nolint:errcheck
|
||||
Method: base.Teardown,
|
||||
URL: c.baseURL,
|
||||
Header: header,
|
||||
}, true)
|
||||
}
|
||||
|
||||
@@ -696,6 +707,8 @@ func (c *Client) reset() {
|
||||
c.useGetParameter = false
|
||||
c.baseURL = nil
|
||||
c.effectiveTransport = nil
|
||||
c.backChannelSetupped = false
|
||||
c.stdChannelSetupped = false
|
||||
c.medias = nil
|
||||
c.tcpCallbackByChannel = nil
|
||||
}
|
||||
@@ -776,13 +789,13 @@ func (c *Client) trySwitchingProtocol2(medi *description.Media, baseURL *base.UR
|
||||
|
||||
func (c *Client) startReadRoutines() {
|
||||
// allocate writer here because it's needed by RTCP receiver / sender
|
||||
if c.state == clientStatePlay {
|
||||
if c.state == clientStateRecord || c.backChannelSetupped {
|
||||
c.writer.allocateBuffer(c.WriteQueueSize)
|
||||
} else {
|
||||
// when reading, buffer is only used to send RTCP receiver reports,
|
||||
// that are much smaller than RTP packets and are sent at a fixed interval.
|
||||
// decrease RAM consumption by allocating less buffers.
|
||||
c.writer.allocateBuffer(8)
|
||||
} else {
|
||||
c.writer.allocateBuffer(c.WriteQueueSize)
|
||||
}
|
||||
|
||||
c.timeDecoder = rtptime.NewGlobalDecoder()
|
||||
@@ -791,7 +804,7 @@ func (c *Client) startReadRoutines() {
|
||||
cm.start()
|
||||
}
|
||||
|
||||
if c.state == clientStatePlay {
|
||||
if c.state == clientStatePlay && c.stdChannelSetupped {
|
||||
c.keepaliveTimer = time.NewTimer(c.keepalivePeriod)
|
||||
|
||||
switch *c.effectiveTransport {
|
||||
@@ -991,7 +1004,7 @@ func (c *Client) isInTCPTimeout() bool {
|
||||
func (c *Client) doCheckTimeout() error {
|
||||
if *c.effectiveTransport == TransportUDP ||
|
||||
*c.effectiveTransport == TransportUDPMulticast {
|
||||
if c.checkTimeoutInitial {
|
||||
if c.checkTimeoutInitial && !c.backChannelSetupped {
|
||||
c.checkTimeoutInitial = false
|
||||
|
||||
if c.atLeastOneUDPPacketHasBeenReceived() {
|
||||
@@ -1092,12 +1105,18 @@ func (c *Client) doDescribe(u *base.URL) (*description.Session, *base.Response,
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
header := base.Header{
|
||||
"Accept": base.HeaderValue{"application/sdp"},
|
||||
}
|
||||
|
||||
if c.RequestBackChannels {
|
||||
header["Require"] = base.HeaderValue{"www.onvif.org/ver20/backchannel"}
|
||||
}
|
||||
|
||||
res, err := c.do(&base.Request{
|
||||
Method: base.Describe,
|
||||
URL: u,
|
||||
Header: base.Header{
|
||||
"Accept": base.HeaderValue{"application/sdp"},
|
||||
},
|
||||
Header: header,
|
||||
}, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -1334,12 +1353,18 @@ func (c *Client) doSetup(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header := base.Header{
|
||||
"Transport": th.Marshal(),
|
||||
}
|
||||
|
||||
if medi.IsBackChannel {
|
||||
header["Require"] = base.HeaderValue{"www.onvif.org/ver20/backchannel"}
|
||||
}
|
||||
|
||||
res, err := c.do(&base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mediaURL,
|
||||
Header: base.Header{
|
||||
"Transport": th.Marshal(),
|
||||
},
|
||||
Header: header,
|
||||
}, false)
|
||||
if err != nil {
|
||||
cm.close()
|
||||
@@ -1509,6 +1534,12 @@ func (c *Client) doSetup(
|
||||
c.baseURL = baseURL
|
||||
c.effectiveTransport = &desiredTransport
|
||||
|
||||
if medi.IsBackChannel {
|
||||
c.backChannelSetupped = true
|
||||
} else {
|
||||
c.stdChannelSetupped = true
|
||||
}
|
||||
|
||||
if c.state == clientStateInitial {
|
||||
c.state = clientStatePrePlay
|
||||
}
|
||||
@@ -1590,12 +1621,18 @@ func (c *Client) doPlay(ra *headers.Range) (*base.Response, error) {
|
||||
}
|
||||
}
|
||||
|
||||
header := base.Header{
|
||||
"Range": ra.Marshal(),
|
||||
}
|
||||
|
||||
if c.backChannelSetupped {
|
||||
header["Require"] = base.HeaderValue{"www.onvif.org/ver20/backchannel"}
|
||||
}
|
||||
|
||||
res, err := c.do(&base.Request{
|
||||
Method: base.Play,
|
||||
URL: c.baseURL,
|
||||
Header: base.Header{
|
||||
"Range": ra.Marshal(),
|
||||
},
|
||||
Header: header,
|
||||
}, false)
|
||||
if err != nil {
|
||||
c.stopReadRoutines()
|
||||
|
Reference in New Issue
Block a user