mirror of
https://github.com/bluenviron/mediamtx
synced 2024-12-17 04:04:41 +00:00
move sdp code into gortsplib
This commit is contained in:
parent
3fca02eca3
commit
79d0f2d053
33
client.go
33
client.go
@ -13,7 +13,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aler9/gortsplib"
|
||||
"github.com/aler9/sdp-dirty/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -31,11 +30,11 @@ type clientDescribeReq struct {
|
||||
}
|
||||
|
||||
type clientAnnounceReq struct {
|
||||
res chan error
|
||||
client *client
|
||||
pathName string
|
||||
sdpText []byte
|
||||
sdpParsed *sdp.SessionDescription
|
||||
res chan error
|
||||
client *client
|
||||
pathName string
|
||||
trackCount int
|
||||
sdp []byte
|
||||
}
|
||||
|
||||
type clientSetupPlayReq struct {
|
||||
@ -449,29 +448,21 @@ func (c *client) handleRequest(req *gortsplib.Request) error {
|
||||
return errRunTerminate
|
||||
}
|
||||
|
||||
sdpParsed := &sdp.SessionDescription{}
|
||||
err = sdpParsed.Unmarshal(req.Content)
|
||||
tracks, err := gortsplib.ReadTracks(req.Content)
|
||||
if err != nil {
|
||||
c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("invalid SDP: %s", err))
|
||||
return errRunTerminate
|
||||
}
|
||||
|
||||
if len(sdpParsed.MediaDescriptions) == 0 {
|
||||
if len(tracks) == 0 {
|
||||
c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("no tracks defined"))
|
||||
return errRunTerminate
|
||||
}
|
||||
|
||||
var tracks []*gortsplib.Track
|
||||
for i, media := range sdpParsed.MediaDescriptions {
|
||||
tracks = append(tracks, &gortsplib.Track{
|
||||
Id: i,
|
||||
Media: media,
|
||||
})
|
||||
}
|
||||
sdpParsed, req.Content = sdpForServer(tracks)
|
||||
sdp := tracks.Write()
|
||||
|
||||
res := make(chan error)
|
||||
c.p.clientAnnounce <- clientAnnounceReq{res, c, pathName, req.Content, sdpParsed}
|
||||
c.p.clientAnnounce <- clientAnnounceReq{res, c, pathName, len(tracks), sdp}
|
||||
err = <-res
|
||||
if err != nil {
|
||||
c.writeResError(cseq, gortsplib.StatusBadRequest, err)
|
||||
@ -669,7 +660,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error {
|
||||
return errRunTerminate
|
||||
}
|
||||
|
||||
if len(c.streamTracks) >= len(c.path.publisherSdpParsed.MediaDescriptions) {
|
||||
if len(c.streamTracks) >= c.path.publisherTrackCount {
|
||||
c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("all the tracks have already been setup"))
|
||||
return errRunTerminate
|
||||
}
|
||||
@ -719,7 +710,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error {
|
||||
return errRunTerminate
|
||||
}
|
||||
|
||||
if len(c.streamTracks) >= len(c.path.publisherSdpParsed.MediaDescriptions) {
|
||||
if len(c.streamTracks) >= c.path.publisherTrackCount {
|
||||
c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("all the tracks have already been setup"))
|
||||
return errRunTerminate
|
||||
}
|
||||
@ -802,7 +793,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error {
|
||||
return errRunTerminate
|
||||
}
|
||||
|
||||
if len(c.streamTracks) != len(c.path.publisherSdpParsed.MediaDescriptions) {
|
||||
if len(c.streamTracks) != c.path.publisherTrackCount {
|
||||
c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("not all tracks have been setup"))
|
||||
return errRunTerminate
|
||||
}
|
||||
|
3
go.mod
3
go.mod
@ -5,8 +5,7 @@ go 1.12
|
||||
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-20200905105840-e895fcfc3776
|
||||
github.com/aler9/sdp-dirty/v3 v3.0.0-20200905103724-214b7cc25cfd
|
||||
github.com/aler9/gortsplib v0.0.0-20200905123647-6d46442a79c9
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||
|
4
go.sum
4
go.sum
@ -2,8 +2,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/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-20200905105840-e895fcfc3776 h1:sQA2DjBj1VHYja5znLKmyIcSKv1/+kpyAn6qg/1WYJQ=
|
||||
github.com/aler9/gortsplib v0.0.0-20200905105840-e895fcfc3776/go.mod h1:XybE/Zt1yFtnNEjNhAyg2w6VjD8aJ79GFfpSjkfLNd8=
|
||||
github.com/aler9/gortsplib v0.0.0-20200905123647-6d46442a79c9 h1:0igRBY+6YHv6YoAB5WTftCf6pFnoItrSy7NrQV8tfco=
|
||||
github.com/aler9/gortsplib v0.0.0-20200905123647-6d46442a79c9/go.mod h1:XybE/Zt1yFtnNEjNhAyg2w6VjD8aJ79GFfpSjkfLNd8=
|
||||
github.com/aler9/sdp-dirty/v3 v3.0.0-20200905103724-214b7cc25cfd h1:s/l20rPNGiyjggMdkhsLu0aQ0K0OFcROUMBDu7fGT+I=
|
||||
github.com/aler9/sdp-dirty/v3 v3.0.0-20200905103724-214b7cc25cfd/go.mod h1:5bO/aUQr9m3OasDatNNcVqKAgs7r5hgGXmszWHaC6mI=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
|
6
main.go
6
main.go
@ -242,8 +242,8 @@ outer:
|
||||
}
|
||||
|
||||
p.paths[req.pathName].publisher = req.client
|
||||
p.paths[req.pathName].publisherSdpText = req.sdpText
|
||||
p.paths[req.pathName].publisherSdpParsed = req.sdpParsed
|
||||
p.paths[req.pathName].publisherTrackCount = req.trackCount
|
||||
p.paths[req.pathName].publisherSdp = req.sdp
|
||||
|
||||
req.client.path = p.paths[req.pathName]
|
||||
req.client.state = clientStatePreRecord
|
||||
@ -256,7 +256,7 @@ outer:
|
||||
continue
|
||||
}
|
||||
|
||||
if req.trackId >= len(path.publisherSdpParsed.MediaDescriptions) {
|
||||
if req.trackId >= path.publisherTrackCount {
|
||||
req.res <- fmt.Errorf("track %d does not exist", req.trackId)
|
||||
continue
|
||||
}
|
||||
|
10
path.go
10
path.go
@ -5,8 +5,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/aler9/sdp-dirty/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,8 +26,8 @@ type path struct {
|
||||
source *source
|
||||
publisher publisher
|
||||
publisherReady bool
|
||||
publisherSdpText []byte
|
||||
publisherSdpParsed *sdp.SessionDescription
|
||||
publisherTrackCount int
|
||||
publisherSdp []byte
|
||||
lastDescribeReq time.Time
|
||||
lastDescribeActivation time.Time
|
||||
onInitCmd *exec.Cmd
|
||||
@ -206,7 +204,7 @@ func (pa *path) onPublisherSetReady() {
|
||||
c.path == pa {
|
||||
c.path = nil
|
||||
c.state = clientStateInitial
|
||||
c.describe <- describeRes{pa.publisherSdpText, nil}
|
||||
c.describe <- describeRes{pa.publisherSdp, nil}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -269,6 +267,6 @@ func (pa *path) onDescribe(client *client) {
|
||||
|
||||
// publisher was found and is ready
|
||||
} else {
|
||||
client.describe <- describeRes{pa.publisherSdpText, nil}
|
||||
client.describe <- describeRes{pa.publisherSdp, nil}
|
||||
}
|
||||
}
|
||||
|
@ -176,11 +176,11 @@ func (s *source) runInnerInner() bool {
|
||||
}
|
||||
|
||||
// create a filtered SDP that is used by the server (not by the client)
|
||||
serverSdpParsed, serverSdpText := sdpForServer(tracks)
|
||||
serverSdp := tracks.Write()
|
||||
|
||||
s.tracks = tracks
|
||||
s.path.publisherSdpText = serverSdpText
|
||||
s.path.publisherSdpParsed = serverSdpParsed
|
||||
s.path.publisherTrackCount = len(tracks)
|
||||
s.path.publisherSdp = serverSdp
|
||||
|
||||
if s.confp.sourceProtocolParsed == gortsplib.StreamProtocolUDP {
|
||||
return s.runUDP(conn)
|
||||
|
56
utils.go
56
utils.go
@ -4,10 +4,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/aler9/gortsplib"
|
||||
"github.com/aler9/sdp-dirty/v3"
|
||||
)
|
||||
|
||||
func parseIpCidrList(in []string) ([]interface{}, error) {
|
||||
@ -76,58 +72,6 @@ func (mb *multiBuffer) next() []byte {
|
||||
return ret
|
||||
}
|
||||
|
||||
// generate a sdp from scratch
|
||||
func sdpForServer(tracks []*gortsplib.Track) (*sdp.SessionDescription, []byte) {
|
||||
sout := &sdp.SessionDescription{
|
||||
SessionName: func() *sdp.SessionName {
|
||||
ret := sdp.SessionName("Stream")
|
||||
return &ret
|
||||
}(),
|
||||
Origin: &sdp.Origin{
|
||||
Username: "-",
|
||||
NetworkType: "IN",
|
||||
AddressType: "IP4",
|
||||
UnicastAddress: "127.0.0.1",
|
||||
},
|
||||
TimeDescriptions: []sdp.TimeDescription{
|
||||
{Timing: sdp.Timing{0, 0}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, track := range tracks {
|
||||
mout := &sdp.MediaDescription{
|
||||
MediaName: sdp.MediaName{
|
||||
Media: track.Media.MediaName.Media,
|
||||
Protos: []string{"RTP", "AVP"}, // override protocol
|
||||
Formats: track.Media.MediaName.Formats,
|
||||
},
|
||||
Bandwidth: track.Media.Bandwidth,
|
||||
Attributes: func() []sdp.Attribute {
|
||||
var ret []sdp.Attribute
|
||||
|
||||
for _, attr := range track.Media.Attributes {
|
||||
if attr.Key == "rtpmap" || attr.Key == "fmtp" {
|
||||
ret = append(ret, attr)
|
||||
}
|
||||
}
|
||||
|
||||
// control attribute is the path that is appended
|
||||
// to the stream path in SETUP
|
||||
ret = append(ret, sdp.Attribute{
|
||||
Key: "control",
|
||||
Value: "trackID=" + strconv.FormatInt(int64(i), 10),
|
||||
})
|
||||
|
||||
return ret
|
||||
}(),
|
||||
}
|
||||
sout.MediaDescriptions = append(sout.MediaDescriptions, mout)
|
||||
}
|
||||
|
||||
bytsout, _ := sout.Marshal()
|
||||
return sout, bytsout
|
||||
}
|
||||
|
||||
func splitPath(path string) (string, string, error) {
|
||||
pos := func() int {
|
||||
for i := len(path) - 1; i >= 0; i-- {
|
||||
|
Loading…
Reference in New Issue
Block a user