mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 23:26:54 +08:00
switch to golangci-lint
This commit is contained in:
25
.github/workflows/lint.yml
vendored
Normal file
25
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: lint
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: golangci/golangci-lint-action@v2
|
||||||
|
with:
|
||||||
|
version: v1.33
|
||||||
|
args: >
|
||||||
|
--disable=errcheck
|
||||||
|
--enable=gofmt
|
||||||
|
--enable=golint
|
||||||
|
--enable=misspell
|
12
Makefile
12
Makefile
@@ -10,7 +10,8 @@ help:
|
|||||||
@echo ""
|
@echo ""
|
||||||
@echo " mod-tidy run go mod tidy"
|
@echo " mod-tidy run go mod tidy"
|
||||||
@echo " format format source files"
|
@echo " format format source files"
|
||||||
@echo " test run available tests"
|
@echo " test run tests"
|
||||||
|
@echo " lint run linter"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
blank :=
|
blank :=
|
||||||
@@ -51,3 +52,12 @@ test-nodocker:
|
|||||||
docker build -q testimages/$(IMG) -t gortsplib-test-$(IMG)$(NL))
|
docker build -q testimages/$(IMG) -t gortsplib-test-$(IMG)$(NL))
|
||||||
go test -race -v ./...
|
go test -race -v ./...
|
||||||
$(foreach f,$(shell ls examples/*),go build -o /dev/null $(f)$(NL))
|
$(foreach f,$(shell ls examples/*),go build -o /dev/null $(f)$(NL))
|
||||||
|
|
||||||
|
lint:
|
||||||
|
docker run --rm -v $(PWD):/app -w /app \
|
||||||
|
golangci/golangci-lint:v1.33.0 \
|
||||||
|
golangci-lint run -v \
|
||||||
|
--disable=errcheck \
|
||||||
|
--enable=gofmt \
|
||||||
|
--enable=golint \
|
||||||
|
--enable=misspell
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
# gortsplib
|
# gortsplib
|
||||||
|
|
||||||
[](https://github.com/aler9/gortsplib/actions)
|
[](https://github.com/aler9/gortsplib/actions)
|
||||||
[](https://goreportcard.com/report/github.com/aler9/gortsplib)
|
[](https://github.com/aler9/gortsplib/actions)
|
||||||
[](https://pkg.go.dev/github.com/aler9/gortsplib)
|
[](https://pkg.go.dev/github.com/aler9/gortsplib)
|
||||||
|
|
||||||
RTSP 1.0 client and server library for the Go programming language, written for [rtsp-simple-server](https://github.com/aler9/rtsp-simple-server).
|
RTSP 1.0 client and server library for the Go programming language, written for [rtsp-simple-server](https://github.com/aler9/rtsp-simple-server).
|
||||||
|
@@ -71,7 +71,7 @@ type ConnClient struct {
|
|||||||
cseq int
|
cseq int
|
||||||
auth *auth.Client
|
auth *auth.Client
|
||||||
state connClientState
|
state connClientState
|
||||||
streamUrl *base.URL
|
streamURL *base.URL
|
||||||
streamProtocol *StreamProtocol
|
streamProtocol *StreamProtocol
|
||||||
tracks Tracks
|
tracks Tracks
|
||||||
udpRtpListeners map[int]*connClientUDPListener
|
udpRtpListeners map[int]*connClientUDPListener
|
||||||
@@ -104,8 +104,8 @@ func (c *ConnClient) Close() error {
|
|||||||
<-c.backgroundDone
|
<-c.backgroundDone
|
||||||
|
|
||||||
c.Do(&base.Request{
|
c.Do(&base.Request{
|
||||||
Method: base.TEARDOWN,
|
Method: base.Teardown,
|
||||||
URL: c.streamUrl,
|
URL: c.streamURL,
|
||||||
SkipResponse: true,
|
SkipResponse: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ func (c *ConnClient) Do(req *base.Request) (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert cseq
|
// insert cseq
|
||||||
c.cseq += 1
|
c.cseq++
|
||||||
req.Header["CSeq"] = base.HeaderValue{strconv.FormatInt(int64(c.cseq), 10)}
|
req.Header["CSeq"] = base.HeaderValue{strconv.FormatInt(int64(c.cseq), 10)}
|
||||||
|
|
||||||
c.nconn.SetWriteDeadline(time.Now().Add(c.d.WriteTimeout))
|
c.nconn.SetWriteDeadline(time.Now().Add(c.d.WriteTimeout))
|
||||||
@@ -241,7 +241,7 @@ func (c *ConnClient) Options(u *base.URL) (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.OPTIONS,
|
Method: base.Options,
|
||||||
URL: u,
|
URL: u,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -264,7 +264,7 @@ func (c *ConnClient) Options(u *base.URL) (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range strings.Split(pub[0], ",") {
|
for _, m := range strings.Split(pub[0], ",") {
|
||||||
if base.Method(m) == base.GET_PARAMETER {
|
if base.Method(m) == base.GetParameter {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,7 +286,7 @@ func (c *ConnClient) Describe(u *base.URL) (Tracks, *base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.DESCRIBE,
|
Method: base.Describe,
|
||||||
URL: u,
|
URL: u,
|
||||||
Header: base.Header{
|
Header: base.Header{
|
||||||
"Accept": base.HeaderValue{"application/sdp"},
|
"Accept": base.HeaderValue{"application/sdp"},
|
||||||
@@ -314,7 +314,7 @@ func (c *ConnClient) Describe(u *base.URL) (Tracks, *base.Response, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
*c = *nc
|
*c = *nc //nolint:govet
|
||||||
|
|
||||||
_, err = c.Options(u)
|
_, err = c.Options(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -342,7 +342,7 @@ func (c *ConnClient) Describe(u *base.URL) (Tracks, *base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range tracks {
|
for _, t := range tracks {
|
||||||
t.BaseUrl = u
|
t.BaseURL = u
|
||||||
}
|
}
|
||||||
|
|
||||||
return tracks, res, nil
|
return tracks, res, nil
|
||||||
@@ -371,7 +371,7 @@ func (c *ConnClient) Setup(mode headers.TransportMode, track *Track,
|
|||||||
return nil, fmt.Errorf("cannot read and publish at the same time")
|
return nil, fmt.Errorf("cannot read and publish at the same time")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.streamUrl != nil && *track.BaseUrl != *c.streamUrl {
|
if c.streamURL != nil && *track.BaseURL != *c.streamURL {
|
||||||
return nil, fmt.Errorf("cannot setup tracks with different base urls")
|
return nil, fmt.Errorf("cannot setup tracks with different base urls")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,10 +457,10 @@ func (c *ConnClient) Setup(mode headers.TransportMode, track *Track,
|
|||||||
transport.ClientPorts = &[2]int{rtpPort, rtcpPort}
|
transport.ClientPorts = &[2]int{rtpPort, rtcpPort}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
transport.InterleavedIds = &[2]int{(track.Id * 2), (track.Id * 2) + 1}
|
transport.InterleavedIds = &[2]int{(track.ID * 2), (track.ID * 2) + 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackUrl, err := track.Url()
|
trackURL, err := track.URL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if proto == StreamProtocolUDP {
|
if proto == StreamProtocolUDP {
|
||||||
rtpListener.close()
|
rtpListener.close()
|
||||||
@@ -470,8 +470,8 @@ func (c *ConnClient) Setup(mode headers.TransportMode, track *Track,
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.SETUP,
|
Method: base.Setup,
|
||||||
URL: trackUrl,
|
URL: trackURL,
|
||||||
Header: base.Header{
|
Header: base.Header{
|
||||||
"Transport": transport.Write(),
|
"Transport": transport.Write(),
|
||||||
},
|
},
|
||||||
@@ -539,34 +539,34 @@ func (c *ConnClient) Setup(mode headers.TransportMode, track *Track,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if mode == headers.TransportModePlay {
|
if mode == headers.TransportModePlay {
|
||||||
c.rtcpReceivers[track.Id] = rtcpreceiver.New(nil, clockRate)
|
c.rtcpReceivers[track.ID] = rtcpreceiver.New(nil, clockRate)
|
||||||
|
|
||||||
if proto == StreamProtocolUDP {
|
if proto == StreamProtocolUDP {
|
||||||
v := time.Now().Unix()
|
v := time.Now().Unix()
|
||||||
c.udpLastFrameTimes[track.Id] = &v
|
c.udpLastFrameTimes[track.ID] = &v
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.rtcpSenders[track.Id] = rtcpsender.New(clockRate)
|
c.rtcpSenders[track.ID] = rtcpsender.New(clockRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.streamUrl = track.BaseUrl
|
c.streamURL = track.BaseURL
|
||||||
c.streamProtocol = &proto
|
c.streamProtocol = &proto
|
||||||
c.tracks = append(c.tracks, track)
|
c.tracks = append(c.tracks, track)
|
||||||
|
|
||||||
if proto == StreamProtocolUDP {
|
if proto == StreamProtocolUDP {
|
||||||
rtpListener.remoteIp = c.nconn.RemoteAddr().(*net.TCPAddr).IP
|
rtpListener.remoteIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
|
||||||
rtpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
rtpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
||||||
rtpListener.remotePort = (*th.ServerPorts)[0]
|
rtpListener.remotePort = (*th.ServerPorts)[0]
|
||||||
rtpListener.trackId = track.Id
|
rtpListener.trackID = track.ID
|
||||||
rtpListener.streamType = StreamTypeRtp
|
rtpListener.streamType = StreamTypeRtp
|
||||||
c.udpRtpListeners[track.Id] = rtpListener
|
c.udpRtpListeners[track.ID] = rtpListener
|
||||||
|
|
||||||
rtcpListener.remoteIp = c.nconn.RemoteAddr().(*net.TCPAddr).IP
|
rtcpListener.remoteIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
|
||||||
rtcpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
rtcpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
||||||
rtcpListener.remotePort = (*th.ServerPorts)[1]
|
rtcpListener.remotePort = (*th.ServerPorts)[1]
|
||||||
rtcpListener.trackId = track.Id
|
rtcpListener.trackID = track.ID
|
||||||
rtcpListener.streamType = StreamTypeRtcp
|
rtcpListener.streamType = StreamTypeRtcp
|
||||||
c.udpRtcpListeners[track.Id] = rtcpListener
|
c.udpRtcpListeners[track.ID] = rtcpListener
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == headers.TransportModePlay {
|
if mode == headers.TransportModePlay {
|
||||||
@@ -593,8 +593,8 @@ func (c *ConnClient) Pause() (*base.Response, error) {
|
|||||||
<-c.backgroundDone
|
<-c.backgroundDone
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.PAUSE,
|
Method: base.Pause,
|
||||||
URL: c.streamUrl,
|
URL: c.streamURL,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -21,8 +21,8 @@ func (c *ConnClient) Announce(u *base.URL, tracks Tracks) (*base.Response, error
|
|||||||
|
|
||||||
// set id, base url and control attribute on tracks
|
// set id, base url and control attribute on tracks
|
||||||
for i, t := range tracks {
|
for i, t := range tracks {
|
||||||
t.Id = i
|
t.ID = i
|
||||||
t.BaseUrl = u
|
t.BaseURL = u
|
||||||
|
|
||||||
t.Media.Attributes = append(t.Media.Attributes, psdp.Attribute{
|
t.Media.Attributes = append(t.Media.Attributes, psdp.Attribute{
|
||||||
Key: "control",
|
Key: "control",
|
||||||
@@ -31,7 +31,7 @@ func (c *ConnClient) Announce(u *base.URL, tracks Tracks) (*base.Response, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.ANNOUNCE,
|
Method: base.Announce,
|
||||||
URL: u,
|
URL: u,
|
||||||
Header: base.Header{
|
Header: base.Header{
|
||||||
"Content-Type": base.HeaderValue{"application/sdp"},
|
"Content-Type": base.HeaderValue{"application/sdp"},
|
||||||
@@ -46,7 +46,7 @@ func (c *ConnClient) Announce(u *base.URL, tracks Tracks) (*base.Response, error
|
|||||||
return nil, fmt.Errorf("bad status code: %d (%s)", res.StatusCode, res.StatusMessage)
|
return nil, fmt.Errorf("bad status code: %d (%s)", res.StatusCode, res.StatusMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.streamUrl = u
|
c.streamURL = u
|
||||||
c.state = connClientStatePreRecord
|
c.state = connClientStatePreRecord
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
@@ -63,8 +63,8 @@ func (c *ConnClient) Record() (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.RECORD,
|
Method: base.Record,
|
||||||
URL: c.streamUrl,
|
URL: c.streamURL,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -126,10 +126,10 @@ func (c *ConnClient) backgroundRecordUDP() {
|
|||||||
case <-reportTicker.C:
|
case <-reportTicker.C:
|
||||||
c.publishWriteMutex.Lock()
|
c.publishWriteMutex.Lock()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for trackId := range c.rtcpSenders {
|
for trackID := range c.rtcpSenders {
|
||||||
r := c.rtcpSenders[trackId].Report(now)
|
r := c.rtcpSenders[trackID].Report(now)
|
||||||
if r != nil {
|
if r != nil {
|
||||||
c.udpRtcpListeners[trackId].write(r)
|
c.udpRtcpListeners[trackID].write(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.publishWriteMutex.Unlock()
|
c.publishWriteMutex.Unlock()
|
||||||
@@ -161,12 +161,12 @@ func (c *ConnClient) backgroundRecordTCP() {
|
|||||||
case <-reportTicker.C:
|
case <-reportTicker.C:
|
||||||
c.publishWriteMutex.Lock()
|
c.publishWriteMutex.Lock()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for trackId := range c.rtcpSenders {
|
for trackID := range c.rtcpSenders {
|
||||||
r := c.rtcpSenders[trackId].Report(now)
|
r := c.rtcpSenders[trackID].Report(now)
|
||||||
if r != nil {
|
if r != nil {
|
||||||
c.nconn.SetWriteDeadline(time.Now().Add(c.d.WriteTimeout))
|
c.nconn.SetWriteDeadline(time.Now().Add(c.d.WriteTimeout))
|
||||||
frame := base.InterleavedFrame{
|
frame := base.InterleavedFrame{
|
||||||
TrackId: trackId,
|
TrackID: trackID,
|
||||||
StreamType: StreamTypeRtcp,
|
StreamType: StreamTypeRtcp,
|
||||||
Content: r,
|
Content: r,
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ func (c *ConnClient) backgroundRecordTCP() {
|
|||||||
|
|
||||||
// WriteFrame writes a frame.
|
// WriteFrame writes a frame.
|
||||||
// This can be called only after Record().
|
// This can be called only after Record().
|
||||||
func (c *ConnClient) WriteFrame(trackId int, streamType StreamType, content []byte) error {
|
func (c *ConnClient) WriteFrame(trackID int, streamType StreamType, content []byte) error {
|
||||||
c.publishWriteMutex.RLock()
|
c.publishWriteMutex.RLock()
|
||||||
defer c.publishWriteMutex.RUnlock()
|
defer c.publishWriteMutex.RUnlock()
|
||||||
|
|
||||||
@@ -190,18 +190,18 @@ func (c *ConnClient) WriteFrame(trackId int, streamType StreamType, content []by
|
|||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
c.rtcpSenders[trackId].ProcessFrame(now, streamType, content)
|
c.rtcpSenders[trackID].ProcessFrame(now, streamType, content)
|
||||||
|
|
||||||
if *c.streamProtocol == StreamProtocolUDP {
|
if *c.streamProtocol == StreamProtocolUDP {
|
||||||
if streamType == StreamTypeRtp {
|
if streamType == StreamTypeRtp {
|
||||||
return c.udpRtpListeners[trackId].write(content)
|
return c.udpRtpListeners[trackID].write(content)
|
||||||
}
|
}
|
||||||
return c.udpRtcpListeners[trackId].write(content)
|
return c.udpRtcpListeners[trackID].write(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.nconn.SetWriteDeadline(now.Add(c.d.WriteTimeout))
|
c.nconn.SetWriteDeadline(now.Add(c.d.WriteTimeout))
|
||||||
frame := base.InterleavedFrame{
|
frame := base.InterleavedFrame{
|
||||||
TrackId: trackId,
|
TrackID: trackID,
|
||||||
StreamType: streamType,
|
StreamType: streamType,
|
||||||
Content: content,
|
Content: content,
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,8 @@ func (c *ConnClient) Play() (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.Do(&base.Request{
|
res, err := c.Do(&base.Request{
|
||||||
Method: base.PLAY,
|
Method: base.Play,
|
||||||
URL: c.streamUrl,
|
URL: c.streamURL,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -39,26 +39,26 @@ func (c *ConnClient) backgroundPlayUDP(onFrameDone chan error) {
|
|||||||
var returnError error
|
var returnError error
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
for trackId := range c.udpRtpListeners {
|
for trackID := range c.udpRtpListeners {
|
||||||
c.udpRtpListeners[trackId].stop()
|
c.udpRtpListeners[trackID].stop()
|
||||||
c.udpRtcpListeners[trackId].stop()
|
c.udpRtcpListeners[trackID].stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
onFrameDone <- returnError
|
onFrameDone <- returnError
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// open the firewall by sending packets to the counterpart
|
// open the firewall by sending packets to the counterpart
|
||||||
for trackId := range c.udpRtpListeners {
|
for trackID := range c.udpRtpListeners {
|
||||||
c.udpRtpListeners[trackId].write(
|
c.udpRtpListeners[trackID].write(
|
||||||
[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
|
|
||||||
c.udpRtcpListeners[trackId].write(
|
c.udpRtcpListeners[trackID].write(
|
||||||
[]byte{0x80, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00})
|
[]byte{0x80, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
|
|
||||||
for trackId := range c.udpRtpListeners {
|
for trackID := range c.udpRtpListeners {
|
||||||
c.udpRtpListeners[trackId].start()
|
c.udpRtpListeners[trackID].start()
|
||||||
c.udpRtcpListeners[trackId].start()
|
c.udpRtcpListeners[trackID].start()
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable deadline
|
// disable deadline
|
||||||
@@ -95,9 +95,9 @@ func (c *ConnClient) backgroundPlayUDP(onFrameDone chan error) {
|
|||||||
|
|
||||||
case <-reportTicker.C:
|
case <-reportTicker.C:
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for trackId := range c.rtcpReceivers {
|
for trackID := range c.rtcpReceivers {
|
||||||
r := c.rtcpReceivers[trackId].Report(now)
|
r := c.rtcpReceivers[trackID].Report(now)
|
||||||
c.udpRtcpListeners[trackId].write(r)
|
c.udpRtcpListeners[trackID].write(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-keepaliveTicker.C:
|
case <-keepaliveTicker.C:
|
||||||
@@ -105,12 +105,12 @@ func (c *ConnClient) backgroundPlayUDP(onFrameDone chan error) {
|
|||||||
Method: func() base.Method {
|
Method: func() base.Method {
|
||||||
// the vlc integrated rtsp server requires GET_PARAMETER
|
// the vlc integrated rtsp server requires GET_PARAMETER
|
||||||
if c.getParameterSupported {
|
if c.getParameterSupported {
|
||||||
return base.GET_PARAMETER
|
return base.GetParameter
|
||||||
}
|
}
|
||||||
return base.OPTIONS
|
return base.Options
|
||||||
}(),
|
}(),
|
||||||
// use the stream path, otherwise some cameras do not reply
|
// use the stream path, otherwise some cameras do not reply
|
||||||
URL: c.streamUrl,
|
URL: c.streamURL,
|
||||||
SkipResponse: true,
|
SkipResponse: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -162,9 +162,9 @@ func (c *ConnClient) backgroundPlayTCP(onFrameDone chan error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.rtcpReceivers[frame.TrackId].ProcessFrame(time.Now(), frame.StreamType, frame.Content)
|
c.rtcpReceivers[frame.TrackID].ProcessFrame(time.Now(), frame.StreamType, frame.Content)
|
||||||
|
|
||||||
c.readCB(frame.TrackId, frame.StreamType, frame.Content)
|
c.readCB(frame.TrackID, frame.StreamType, frame.Content)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -190,11 +190,11 @@ func (c *ConnClient) backgroundPlayTCP(onFrameDone chan error) {
|
|||||||
|
|
||||||
case <-reportTicker.C:
|
case <-reportTicker.C:
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for trackId := range c.rtcpReceivers {
|
for trackID := range c.rtcpReceivers {
|
||||||
r := c.rtcpReceivers[trackId].Report(now)
|
r := c.rtcpReceivers[trackID].Report(now)
|
||||||
c.nconn.SetWriteDeadline(time.Now().Add(c.d.WriteTimeout))
|
c.nconn.SetWriteDeadline(time.Now().Add(c.d.WriteTimeout))
|
||||||
frame := base.InterleavedFrame{
|
frame := base.InterleavedFrame{
|
||||||
TrackId: trackId,
|
TrackID: trackID,
|
||||||
StreamType: StreamTypeRtcp,
|
StreamType: StreamTypeRtcp,
|
||||||
Content: r,
|
Content: r,
|
||||||
}
|
}
|
||||||
|
@@ -19,11 +19,11 @@ const (
|
|||||||
type connClientUDPListener struct {
|
type connClientUDPListener struct {
|
||||||
c *ConnClient
|
c *ConnClient
|
||||||
pc net.PacketConn
|
pc net.PacketConn
|
||||||
remoteIp net.IP
|
remoteIP net.IP
|
||||||
remoteZone string
|
remoteZone string
|
||||||
remotePort int
|
remotePort int
|
||||||
udpFrameBuffer *multibuffer.MultiBuffer
|
udpFrameBuffer *multibuffer.MultiBuffer
|
||||||
trackId int
|
trackID int
|
||||||
streamType StreamType
|
streamType StreamType
|
||||||
running bool
|
running bool
|
||||||
|
|
||||||
@@ -79,22 +79,22 @@ func (l *connClientUDPListener) run() {
|
|||||||
|
|
||||||
uaddr := addr.(*net.UDPAddr)
|
uaddr := addr.(*net.UDPAddr)
|
||||||
|
|
||||||
if !l.remoteIp.Equal(uaddr.IP) || l.remotePort != uaddr.Port {
|
if !l.remoteIP.Equal(uaddr.IP) || l.remotePort != uaddr.Port {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
atomic.StoreInt64(l.c.udpLastFrameTimes[l.trackId], now.Unix())
|
atomic.StoreInt64(l.c.udpLastFrameTimes[l.trackID], now.Unix())
|
||||||
l.c.rtcpReceivers[l.trackId].ProcessFrame(now, l.streamType, buf[:n])
|
l.c.rtcpReceivers[l.trackID].ProcessFrame(now, l.streamType, buf[:n])
|
||||||
|
|
||||||
l.c.readCB(l.trackId, l.streamType, buf[:n])
|
l.c.readCB(l.trackID, l.streamType, buf[:n])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *connClientUDPListener) write(buf []byte) error {
|
func (l *connClientUDPListener) write(buf []byte) error {
|
||||||
l.pc.SetWriteDeadline(time.Now().Add(l.c.d.WriteTimeout))
|
l.pc.SetWriteDeadline(time.Now().Add(l.c.d.WriteTimeout))
|
||||||
_, err := l.pc.WriteTo(buf, &net.UDPAddr{
|
_, err := l.pc.WriteTo(buf, &net.UDPAddr{
|
||||||
IP: l.remoteIp,
|
IP: l.remoteIP,
|
||||||
Zone: l.remoteZone,
|
Zone: l.remoteZone,
|
||||||
Port: l.remotePort,
|
Port: l.remotePort,
|
||||||
})
|
})
|
||||||
|
@@ -322,14 +322,14 @@ func TestDialPublishSerial(t *testing.T) {
|
|||||||
buf := make([]byte, 2048)
|
buf := make([]byte, 2048)
|
||||||
n, _, err := pc.ReadFrom(buf)
|
n, _, err := pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
|
||||||
n, _, err = pc.ReadFrom(buf)
|
n, _, err = pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -420,7 +420,7 @@ func TestDialPublishParallel(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -498,7 +498,7 @@ func TestDialPublishPauseSerial(t *testing.T) {
|
|||||||
|
|
||||||
n, _, err := pc.ReadFrom(buf)
|
n, _, err := pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = conn.Pause()
|
_, err = conn.Pause()
|
||||||
@@ -506,7 +506,7 @@ func TestDialPublishPauseSerial(t *testing.T) {
|
|||||||
|
|
||||||
n, _, err = pc.ReadFrom(buf)
|
n, _, err = pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
_, err = conn.Record()
|
_, err = conn.Record()
|
||||||
@@ -514,7 +514,7 @@ func TestDialPublishPauseSerial(t *testing.T) {
|
|||||||
|
|
||||||
n, _, err = pc.ReadFrom(buf)
|
n, _, err = pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -574,7 +574,7 @@ func TestDialPublishPauseParallel(t *testing.T) {
|
|||||||
n, _, err := pc.ReadFrom(buf)
|
n, _, err := pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = conn.WriteFrame(track.Id, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@@ -105,9 +105,9 @@ func (s *ConnServer) WriteResponse(res *base.Response) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteFrameTCP writes an InterleavedFrame.
|
// WriteFrameTCP writes an InterleavedFrame.
|
||||||
func (s *ConnServer) WriteFrameTCP(trackId int, streamType StreamType, content []byte) error {
|
func (s *ConnServer) WriteFrameTCP(trackID int, streamType StreamType, content []byte) error {
|
||||||
frame := base.InterleavedFrame{
|
frame := base.InterleavedFrame{
|
||||||
TrackId: trackId,
|
TrackID: trackID,
|
||||||
StreamType: streamType,
|
StreamType: streamType,
|
||||||
Content: content,
|
Content: content,
|
||||||
}
|
}
|
||||||
|
@@ -70,7 +70,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write track frames
|
// write track frames
|
||||||
err = conn.WriteFrame(track.Id, gortsplib.StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRtp, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -66,7 +66,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write track frames
|
// write track frames
|
||||||
err = conn.WriteFrame(track.Id, gortsplib.StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRtp, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@@ -58,7 +58,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write track frames
|
// write track frames
|
||||||
err = conn.WriteFrame(track.Id, gortsplib.StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRtp, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -36,10 +36,10 @@ func TestAuthMethods(t *testing.T) {
|
|||||||
|
|
||||||
ac, err := NewClient(wwwAuthenticate, url.UserPassword("testuser", "testpass"))
|
ac, err := NewClient(wwwAuthenticate, url.UserPassword("testuser", "testpass"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
authorization := ac.GenerateHeader(base.ANNOUNCE,
|
authorization := ac.GenerateHeader(base.Announce,
|
||||||
base.MustParseURL("rtsp://myhost/mypath"))
|
base.MustParseURL("rtsp://myhost/mypath"))
|
||||||
|
|
||||||
err = authServer.ValidateHeader(authorization, base.ANNOUNCE,
|
err = authServer.ValidateHeader(authorization, base.Announce,
|
||||||
base.MustParseURL("rtsp://myhost/mypath"))
|
base.MustParseURL("rtsp://myhost/mypath"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
@@ -53,11 +53,11 @@ func TestAuthVLC(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"rtsp://myhost/mypath/",
|
"rtsp://myhost/mypath/",
|
||||||
"rtsp://myhost/mypath/trackId=0",
|
"rtsp://myhost/mypath/trackID=0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rtsp://myhost/mypath/test?testing/",
|
"rtsp://myhost/mypath/test?testing/",
|
||||||
"rtsp://myhost/mypath/test?testing/trackId=0",
|
"rtsp://myhost/mypath/test?testing/trackID=0",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
authServer := NewServer("testuser", "testpass",
|
authServer := NewServer("testuser", "testpass",
|
||||||
@@ -66,10 +66,10 @@ func TestAuthVLC(t *testing.T) {
|
|||||||
|
|
||||||
ac, err := NewClient(wwwAuthenticate, url.UserPassword("testuser", "testpass"))
|
ac, err := NewClient(wwwAuthenticate, url.UserPassword("testuser", "testpass"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
authorization := ac.GenerateHeader(base.ANNOUNCE,
|
authorization := ac.GenerateHeader(base.Announce,
|
||||||
base.MustParseURL(ca.clientURL))
|
base.MustParseURL(ca.clientURL))
|
||||||
|
|
||||||
err = authServer.ValidateHeader(authorization, base.ANNOUNCE,
|
err = authServer.ValidateHeader(authorization, base.Announce,
|
||||||
base.MustParseURL(ca.serverURL))
|
base.MustParseURL(ca.serverURL))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@ func ReadInterleavedFrameOrResponse(frame *InterleavedFrame, res *Response, br *
|
|||||||
// within RTSP/TCP connections. It is used to send and receive RTP and RTCP packets with TCP.
|
// within RTSP/TCP connections. It is used to send and receive RTP and RTCP packets with TCP.
|
||||||
type InterleavedFrame struct {
|
type InterleavedFrame struct {
|
||||||
// track id
|
// track id
|
||||||
TrackId int
|
TrackID int
|
||||||
|
|
||||||
// stream type
|
// stream type
|
||||||
StreamType StreamType
|
StreamType StreamType
|
||||||
@@ -88,9 +88,9 @@ func (f *InterleavedFrame) Read(br *bufio.Reader) error {
|
|||||||
framelen, len(f.Content))
|
framelen, len(f.Content))
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert channel into TrackId and StreamType
|
// convert channel into TrackID and StreamType
|
||||||
channel := header[1]
|
channel := header[1]
|
||||||
f.TrackId, f.StreamType = func() (int, StreamType) {
|
f.TrackID, f.StreamType = func() (int, StreamType) {
|
||||||
if (channel % 2) == 0 {
|
if (channel % 2) == 0 {
|
||||||
return int(channel / 2), StreamTypeRtp
|
return int(channel / 2), StreamTypeRtp
|
||||||
}
|
}
|
||||||
@@ -108,12 +108,12 @@ func (f *InterleavedFrame) Read(br *bufio.Reader) error {
|
|||||||
|
|
||||||
// Write writes an InterleavedFrame into a buffered writer.
|
// Write writes an InterleavedFrame into a buffered writer.
|
||||||
func (f InterleavedFrame) Write(bw *bufio.Writer) error {
|
func (f InterleavedFrame) Write(bw *bufio.Writer) error {
|
||||||
// convert TrackId and StreamType into channel
|
// convert TrackID and StreamType into channel
|
||||||
channel := func() uint8 {
|
channel := func() uint8 {
|
||||||
if f.StreamType == StreamTypeRtp {
|
if f.StreamType == StreamTypeRtp {
|
||||||
return uint8(f.TrackId * 2)
|
return uint8(f.TrackID * 2)
|
||||||
}
|
}
|
||||||
return uint8((f.TrackId * 2) + 1)
|
return uint8((f.TrackID * 2) + 1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
_, err := bw.Write([]byte{0x24, channel})
|
_, err := bw.Write([]byte{0x24, channel})
|
||||||
|
@@ -19,18 +19,18 @@ type Method string
|
|||||||
|
|
||||||
// standard methods
|
// standard methods
|
||||||
const (
|
const (
|
||||||
ANNOUNCE Method = "ANNOUNCE"
|
Announce Method = "ANNOUNCE"
|
||||||
DESCRIBE Method = "DESCRIBE"
|
Describe Method = "DESCRIBE"
|
||||||
GET_PARAMETER Method = "GET_PARAMETER"
|
GetParameter Method = "GET_PARAMETER"
|
||||||
OPTIONS Method = "OPTIONS"
|
Options Method = "OPTIONS"
|
||||||
PAUSE Method = "PAUSE"
|
Pause Method = "PAUSE"
|
||||||
PLAY Method = "PLAY"
|
Play Method = "PLAY"
|
||||||
PLAY_NOTIFY Method = "PLAY_NOTIFY"
|
PlayNotify Method = "PLAY_NOTIFY"
|
||||||
RECORD Method = "RECORD"
|
Record Method = "RECORD"
|
||||||
REDIRECT Method = "REDIRECT"
|
Redirect Method = "REDIRECT"
|
||||||
SETUP Method = "SETUP"
|
Setup Method = "SETUP"
|
||||||
SET_PARAMETER Method = "SET_PARAMETER"
|
SetParameter Method = "SET_PARAMETER"
|
||||||
TEARDOWN Method = "TEARDOWN"
|
Teardown Method = "TEARDOWN"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request is a RTSP request.
|
// Request is a RTSP request.
|
||||||
@@ -68,15 +68,15 @@ func (req *Request) Read(rb *bufio.Reader) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rawUrl := string(byts[:len(byts)-1])
|
rawURL := string(byts[:len(byts)-1])
|
||||||
|
|
||||||
if rawUrl == "" {
|
if rawURL == "" {
|
||||||
return fmt.Errorf("empty url")
|
return fmt.Errorf("empty url")
|
||||||
}
|
}
|
||||||
|
|
||||||
ur, err := ParseURL(rawUrl)
|
ur, err := ParseURL(rawURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to parse url (%v)", rawUrl)
|
return fmt.Errorf("unable to parse url (%v)", rawURL)
|
||||||
}
|
}
|
||||||
req.URL = ur
|
req.URL = ur
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ func New(count int, size int) *MultiBuffer {
|
|||||||
// Next gets the current buffer and sets the next buffer as the current one.
|
// Next gets the current buffer and sets the next buffer as the current one.
|
||||||
func (mb *MultiBuffer) Next() []byte {
|
func (mb *MultiBuffer) Next() []byte {
|
||||||
ret := mb.buffers[mb.cur]
|
ret := mb.buffers[mb.cur]
|
||||||
mb.cur += 1
|
mb.cur++
|
||||||
if mb.cur >= mb.count {
|
if mb.cur >= mb.count {
|
||||||
mb.cur = 0
|
mb.cur = 0
|
||||||
}
|
}
|
||||||
|
@@ -74,7 +74,7 @@ func (rr *RtcpReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, b
|
|||||||
if diff > 0 || diff < -0x0FFF {
|
if diff > 0 || diff < -0x0FFF {
|
||||||
// overflow
|
// overflow
|
||||||
if diff < -0x0FFF {
|
if diff < -0x0FFF {
|
||||||
rr.sequenceNumberCycles += 1
|
rr.sequenceNumberCycles++
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect lost frames
|
// detect lost frames
|
||||||
|
@@ -51,7 +51,7 @@ func (e *Encoder) Write(ts time.Duration, data []byte) ([][]byte, error) {
|
|||||||
// 13 bits payload size
|
// 13 bits payload size
|
||||||
// 3 bits AU-Index(-delta)
|
// 3 bits AU-Index(-delta)
|
||||||
header := make([]byte, 2)
|
header := make([]byte, 2)
|
||||||
binary.BigEndian.PutUint16(header, (uint16(len(data))<<3)|0)
|
binary.BigEndian.PutUint16(header, uint16(len(data))<<3)
|
||||||
|
|
||||||
payload := append([]byte{0x00, 0x10}, header...)
|
payload := append([]byte{0x00, 0x10}, header...)
|
||||||
payload = append(payload, data...)
|
payload = append(payload, data...)
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
//nolint:govet
|
||||||
package sdp
|
package sdp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
24
track.go
24
track.go
@@ -17,10 +17,10 @@ import (
|
|||||||
// Track is a track available in a certain URL.
|
// Track is a track available in a certain URL.
|
||||||
type Track struct {
|
type Track struct {
|
||||||
// base url
|
// base url
|
||||||
BaseUrl *base.URL
|
BaseURL *base.URL
|
||||||
|
|
||||||
// id
|
// id
|
||||||
Id int
|
ID int
|
||||||
|
|
||||||
// codec and info in SDP format
|
// codec and info in SDP format
|
||||||
Media *psdp.MediaDescription
|
Media *psdp.MediaDescription
|
||||||
@@ -30,7 +30,7 @@ type Track struct {
|
|||||||
func NewTrackH264(payloadType uint8, sps []byte, pps []byte) (*Track, error) {
|
func NewTrackH264(payloadType uint8, sps []byte, pps []byte) (*Track, error) {
|
||||||
spropParameterSets := base64.StdEncoding.EncodeToString(sps) +
|
spropParameterSets := base64.StdEncoding.EncodeToString(sps) +
|
||||||
"," + base64.StdEncoding.EncodeToString(pps)
|
"," + base64.StdEncoding.EncodeToString(pps)
|
||||||
profileLevelId := strings.ToUpper(hex.EncodeToString(sps[1:4]))
|
profileLevelID := strings.ToUpper(hex.EncodeToString(sps[1:4]))
|
||||||
|
|
||||||
typ := strconv.FormatInt(int64(payloadType), 10)
|
typ := strconv.FormatInt(int64(payloadType), 10)
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ func NewTrackH264(payloadType uint8, sps []byte, pps []byte) (*Track, error) {
|
|||||||
Key: "fmtp",
|
Key: "fmtp",
|
||||||
Value: typ + " packetization-mode=1; " +
|
Value: typ + " packetization-mode=1; " +
|
||||||
"sprop-parameter-sets=" + spropParameterSets + "; " +
|
"sprop-parameter-sets=" + spropParameterSets + "; " +
|
||||||
"profile-level-id=" + profileLevelId,
|
"profile-level-id=" + profileLevelID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -162,8 +162,8 @@ func (t *Track) ClockRate() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Url returns the track url.
|
// Url returns the track url.
|
||||||
func (t *Track) Url() (*base.URL, error) {
|
func (t *Track) URL() (*base.URL, error) {
|
||||||
if t.BaseUrl == nil {
|
if t.BaseURL == nil {
|
||||||
return nil, fmt.Errorf("empty base url")
|
return nil, fmt.Errorf("empty base url")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ func (t *Track) Url() (*base.URL, error) {
|
|||||||
|
|
||||||
// no control attribute, use base URL
|
// no control attribute, use base URL
|
||||||
if control == "" {
|
if control == "" {
|
||||||
return t.BaseUrl, nil
|
return t.BaseURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// control attribute contains an absolute path
|
// control attribute contains an absolute path
|
||||||
@@ -189,13 +189,13 @@ func (t *Track) Url() (*base.URL, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copy host and credentials
|
// copy host and credentials
|
||||||
ur.Host = t.BaseUrl.Host
|
ur.Host = t.BaseURL.Host
|
||||||
ur.User = t.BaseUrl.User
|
ur.User = t.BaseURL.User
|
||||||
return ur, nil
|
return ur, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// control attribute contains a relative control attribute
|
// control attribute contains a relative control attribute
|
||||||
ur := t.BaseUrl.Clone()
|
ur := t.BaseURL.Clone()
|
||||||
ur.AddControlAttribute(control)
|
ur.AddControlAttribute(control)
|
||||||
return ur, nil
|
return ur, nil
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ func ReadTracks(byts []byte) (Tracks, error) {
|
|||||||
ts := make(Tracks, len(desc.MediaDescriptions))
|
ts := make(Tracks, len(desc.MediaDescriptions))
|
||||||
for i, media := range desc.MediaDescriptions {
|
for i, media := range desc.MediaDescriptions {
|
||||||
ts[i] = &Track{
|
ts[i] = &Track{
|
||||||
Id: i,
|
ID: i,
|
||||||
Media: media,
|
Media: media,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ func (ts Tracks) Write() []byte {
|
|||||||
Address: &psdp.Address{Address: "0.0.0.0"},
|
Address: &psdp.Address{Address: "0.0.0.0"},
|
||||||
},
|
},
|
||||||
TimeDescriptions: []psdp.TimeDescription{
|
TimeDescriptions: []psdp.TimeDescription{
|
||||||
{Timing: psdp.Timing{0, 0}},
|
{Timing: psdp.Timing{0, 0}}, //nolint:govet
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user