update gortsplib

This commit is contained in:
aler9 2020-07-18 13:48:09 +02:00
parent 2396832d52
commit ce5e11f6c9
6 changed files with 57 additions and 49 deletions

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.13
require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/aler9/gortsplib v0.0.0-20200713155346-67368c8ec5f6
github.com/aler9/gortsplib v0.0.0-20200718113358-4754822be147
github.com/pion/sdp v1.3.0
github.com/stretchr/testify v1.5.1
gopkg.in/alecthomas/kingpin.v2 v2.2.6

4
go.sum
View File

@ -2,8 +2,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/aler9/gortsplib v0.0.0-20200713155346-67368c8ec5f6 h1:ndRQ+7v10ok+unOVo6f7PIffg65yUukq2qKgR44xI0I=
github.com/aler9/gortsplib v0.0.0-20200713155346-67368c8ec5f6/go.mod h1:17dcA4Qak5TLqgun8OR0wnSbFQIg4cvYVSf1nbCt+qU=
github.com/aler9/gortsplib v0.0.0-20200718113358-4754822be147 h1:1rPmAAdNf9bdxXWuY9PSko6eFMjwLiwlTXbOukG0cFg=
github.com/aler9/gortsplib v0.0.0-20200718113358-4754822be147/go.mod h1:17dcA4Qak5TLqgun8OR0wnSbFQIg4cvYVSf1nbCt+qU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pion/rtcp v1.2.3 h1:2wrhKnqgSz91Q5nzYTO07mQXztYPtxL8a0XOss4rJqA=

View File

@ -92,7 +92,7 @@ func (c *container) wait() int {
return int(code)
}
func TestProtocols(t *testing.T) {
func TestPublishRead(t *testing.T) {
for _, conf := range [][3]string{
{"udp", "udp", "ffmpeg"},
{"udp", "tcp", "ffmpeg"},

View File

@ -313,7 +313,7 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Public": []string{strings.Join([]string{
"Public": gortsplib.HeaderValue{strings.Join([]string{
string(gortsplib.DESCRIBE),
string(gortsplib.ANNOUNCE),
string(gortsplib.SETUP),
@ -359,8 +359,8 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Content-Base": []string{req.Url.String() + "/"},
"Content-Type": []string{"application/sdp"},
"Content-Base": gortsplib.HeaderValue{req.Url.String() + "/"},
"Content-Type": gortsplib.HeaderValue{"application/sdp"},
},
Content: sdp,
})
@ -410,13 +410,21 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("invalid SDP: %s", err))
return false
}
sdpParsed, req.Content = sdpForServer(sdpParsed)
if len(sdpParsed.MediaDescriptions) == 0 {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("no tracks defined"))
return false
}
var tracks []*gortsplib.Track
for i, media := range sdpParsed.MediaDescriptions {
tracks = append(tracks, &gortsplib.Track{
Id: i,
Media: media,
})
}
sdpParsed, req.Content = sdpForServer(tracks)
res := make(chan error)
c.p.events <- programEventClientAnnounce{res, c, path}
err = <-res
@ -437,13 +445,12 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
return true
case gortsplib.SETUP:
tsRaw, ok := req.Header["Transport"]
if !ok || len(tsRaw) != 1 {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header missing"))
th, err := gortsplib.ReadHeaderTransport(req.Header["Transport"])
if err != nil {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header: %s", err))
return false
}
th := gortsplib.ReadHeaderTransport(tsRaw[0])
if _, ok := th["multicast"]; ok {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("multicast is not supported"))
return false
@ -486,7 +493,7 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
rtpPort, rtcpPort := th.GetPorts("client_port")
if rtpPort == 0 || rtcpPort == 0 {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not have valid client ports (%s)", tsRaw[0]))
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not have valid client ports (%v)", req.Header["Transport"]))
return false
}
@ -512,13 +519,13 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Transport": []string{strings.Join([]string{
"Transport": gortsplib.HeaderValue{strings.Join([]string{
"RTP/AVP/UDP",
"unicast",
fmt.Sprintf("client_port=%d-%d", rtpPort, rtcpPort),
fmt.Sprintf("server_port=%d-%d", c.p.conf.RtpPort, c.p.conf.RtcpPort),
}, ";")},
"Session": []string{"12345678"},
"Session": gortsplib.HeaderValue{"12345678"},
},
})
return true
@ -554,18 +561,18 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Transport": []string{strings.Join([]string{
"Transport": gortsplib.HeaderValue{strings.Join([]string{
"RTP/AVP/TCP",
"unicast",
fmt.Sprintf("interleaved=%s", interleaved),
}, ";")},
"Session": []string{"12345678"},
"Session": gortsplib.HeaderValue{"12345678"},
},
})
return true
} else {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain a valid protocol (RTP/AVP, RTP/AVP/UDP or RTP/AVP/TCP) (%s)", tsRaw[0]))
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain a valid protocol (RTP/AVP, RTP/AVP/UDP or RTP/AVP/TCP) (%s)", req.Header["Transport"]))
return false
}
@ -601,7 +608,7 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
rtpPort, rtcpPort := th.GetPorts("client_port")
if rtpPort == 0 || rtcpPort == 0 {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not have valid client ports (%s)", tsRaw[0]))
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not have valid client ports (%s)", req.Header["Transport"]))
return false
}
@ -627,13 +634,13 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Transport": []string{strings.Join([]string{
"Transport": gortsplib.HeaderValue{strings.Join([]string{
"RTP/AVP/UDP",
"unicast",
fmt.Sprintf("client_port=%d-%d", rtpPort, rtcpPort),
fmt.Sprintf("server_port=%d-%d", c.p.conf.RtpPort, c.p.conf.RtcpPort),
}, ";")},
"Session": []string{"12345678"},
"Session": gortsplib.HeaderValue{"12345678"},
},
})
return true
@ -679,18 +686,18 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Transport": []string{strings.Join([]string{
"Transport": gortsplib.HeaderValue{strings.Join([]string{
"RTP/AVP/TCP",
"unicast",
fmt.Sprintf("interleaved=%s", interleaved),
}, ";")},
"Session": []string{"12345678"},
"Session": gortsplib.HeaderValue{"12345678"},
},
})
return true
} else {
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain a valid protocol (RTP/AVP, RTP/AVP/UDP or RTP/AVP/TCP) (%s)", tsRaw[0]))
c.writeResError(req, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain a valid protocol (RTP/AVP, RTP/AVP/UDP or RTP/AVP/TCP) (%s)", req.Header["Transport"]))
return false
}
@ -727,7 +734,7 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Session": []string{"12345678"},
"Session": gortsplib.HeaderValue{"12345678"},
},
})
@ -755,7 +762,7 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
StatusCode: gortsplib.StatusOK,
Header: gortsplib.Header{
"CSeq": cseq,
"Session": []string{"12345678"},
"Session": gortsplib.HeaderValue{"12345678"},
},
})

View File

@ -29,7 +29,7 @@ type source struct {
u *url.URL
proto streamProtocol
ready bool
clientSdpParsed *sdp.SessionDescription
clientTracks []*gortsplib.Track
serverSdpText []byte
serverSdpParsed *sdp.SessionDescription
rtcpReceivers []*gortsplib.RtcpReceiver
@ -155,16 +155,16 @@ func (s *source) do() bool {
return true
}
clientSdpParsed, _, err := conn.Describe(s.u)
clientTracks, _, err := conn.Describe(s.u)
if err != nil {
s.log("ERR: %s", err)
return true
}
// create a filtered SDP that is used by the server (not by the client)
serverSdpParsed, serverSdpText := sdpForServer(clientSdpParsed)
serverSdpParsed, serverSdpText := sdpForServer(clientTracks)
s.clientSdpParsed = clientSdpParsed
s.clientTracks = clientTracks
s.serverSdpText = serverSdpText
s.serverSdpParsed = serverSdpParsed
@ -187,7 +187,7 @@ func (s *source) runUdp(conn *gortsplib.ConnClient) bool {
}
}()
for i, media := range s.clientSdpParsed.MediaDescriptions {
for i, track := range s.clientTracks {
var rtpPort int
var rtcpPort int
var rtpl *sourceUdpListener
@ -217,7 +217,7 @@ func (s *source) runUdp(conn *gortsplib.ConnClient) bool {
}
}()
rtpServerPort, rtcpServerPort, _, err := conn.SetupUdp(s.u, media, rtpPort, rtcpPort)
rtpServerPort, rtcpServerPort, _, err := conn.SetupUdp(s.u, track, rtpPort, rtcpPort)
if err != nil {
s.log("ERR: %s", err)
rtpl.close()
@ -240,8 +240,8 @@ func (s *source) runUdp(conn *gortsplib.ConnClient) bool {
return true
}
s.rtcpReceivers = make([]*gortsplib.RtcpReceiver, len(s.clientSdpParsed.MediaDescriptions))
for trackId := range s.clientSdpParsed.MediaDescriptions {
s.rtcpReceivers = make([]*gortsplib.RtcpReceiver, len(s.clientTracks))
for trackId := range s.clientTracks {
s.rtcpReceivers[trackId] = gortsplib.NewRtcpReceiver()
}
@ -274,7 +274,7 @@ outer:
}
case <-checkStreamTicker.C:
for trackId := range s.clientSdpParsed.MediaDescriptions {
for trackId := range s.clientTracks {
if time.Since(s.rtcpReceivers[trackId].LastFrameTime()) >= s.p.conf.StreamDeadAfter {
s.log("ERR: stream is dead")
ret = true
@ -283,7 +283,7 @@ outer:
}
case <-receiverReportTicker.C:
for trackId := range s.clientSdpParsed.MediaDescriptions {
for trackId := range s.clientTracks {
frame := s.rtcpReceivers[trackId].Report()
sourceUdpListenerPairs[trackId].rtcpl.writeChan <- &udpAddrBufPair{
addr: &net.UDPAddr{
@ -308,7 +308,7 @@ outer:
pair.rtcpl.stop()
}
for trackId := range s.clientSdpParsed.MediaDescriptions {
for trackId := range s.clientTracks {
s.rtcpReceivers[trackId].Close()
}
@ -316,8 +316,8 @@ outer:
}
func (s *source) runTcp(conn *gortsplib.ConnClient) bool {
for i, media := range s.clientSdpParsed.MediaDescriptions {
_, err := conn.SetupTcp(s.u, media, i)
for _, track := range s.clientTracks {
_, err := conn.SetupTcp(s.u, track)
if err != nil {
s.log("ERR: %s", err)
return true
@ -330,8 +330,8 @@ func (s *source) runTcp(conn *gortsplib.ConnClient) bool {
return true
}
s.rtcpReceivers = make([]*gortsplib.RtcpReceiver, len(s.clientSdpParsed.MediaDescriptions))
for trackId := range s.clientSdpParsed.MediaDescriptions {
s.rtcpReceivers = make([]*gortsplib.RtcpReceiver, len(s.clientTracks))
for trackId := range s.clientTracks {
s.rtcpReceivers[trackId] = gortsplib.NewRtcpReceiver()
}
@ -375,7 +375,7 @@ outer:
break outer
case <-receiverReportTicker.C:
for trackId := range s.clientSdpParsed.MediaDescriptions {
for trackId := range s.clientTracks {
frame := s.rtcpReceivers[trackId].Report()
conn.WriteFrame(&gortsplib.InterleavedFrame{
@ -391,7 +391,7 @@ outer:
s.p.events <- programEventStreamerNotReady{s}
for trackId := range s.clientSdpParsed.MediaDescriptions {
for trackId := range s.clientTracks {
s.rtcpReceivers[trackId].Close()
}

View File

@ -5,6 +5,7 @@ import (
"net"
"strconv"
"github.com/aler9/gortsplib"
"github.com/pion/sdp"
)
@ -73,7 +74,7 @@ func (db *doubleBuffer) swap() []byte {
return ret
}
func sdpForServer(sin *sdp.SessionDescription) (*sdp.SessionDescription, []byte) {
func sdpForServer(tracks []*gortsplib.Track) (*sdp.SessionDescription, []byte) {
sout := &sdp.SessionDescription{
SessionName: "Stream",
Origin: sdp.Origin{
@ -87,18 +88,18 @@ func sdpForServer(sin *sdp.SessionDescription) (*sdp.SessionDescription, []byte)
},
}
for i, min := range sin.MediaDescriptions {
for i, track := range tracks {
mout := &sdp.MediaDescription{
MediaName: sdp.MediaName{
Media: min.MediaName.Media,
Media: track.Media.MediaName.Media,
Protos: []string{"RTP", "AVP"}, // override protocol
Formats: min.MediaName.Formats,
Formats: track.Media.MediaName.Formats,
},
Bandwidth: min.Bandwidth,
Bandwidth: track.Media.Bandwidth,
Attributes: func() []sdp.Attribute {
var ret []sdp.Attribute
for _, attr := range min.Attributes {
for _, attr := range track.Media.Attributes {
if attr.Key == "rtpmap" || attr.Key == "fmtp" {
ret = append(ret, attr)
}