Browse Source

improve performance by using int states instead of strings

pull/2/head
aler9 6 years ago
parent
commit
16e4fcb372
  1. 57
      client.go
  2. 2
      main.go

57
client.go

@ -26,10 +26,21 @@ func trackToInterleavedChannel(id int, flow trackFlow) int {
return (id * 2) + 1 return (id * 2) + 1
} }
type clientState int
const (
_CLIENT_STATE_STARTING clientState = iota
_CLIENT_STATE_ANNOUNCE
_CLIENT_STATE_PRE_PLAY
_CLIENT_STATE_PLAY
_CLIENT_STATE_PRE_RECORD
_CLIENT_STATE_RECORD
)
type client struct { type client struct {
p *program p *program
rconn *gortsplib.Conn rconn *gortsplib.Conn
state string state clientState
ip net.IP ip net.IP
path string path string
streamSdpText []byte // filled only if publisher streamSdpText []byte // filled only if publisher
@ -42,7 +53,7 @@ func newClient(p *program, nconn net.Conn) *client {
c := &client{ c := &client{
p: p, p: p,
rconn: gortsplib.NewConn(nconn), rconn: gortsplib.NewConn(nconn),
state: "STARTING", state: _CLIENT_STATE_STARTING,
} }
c.p.mutex.Lock() c.p.mutex.Lock()
@ -189,8 +200,8 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
return true return true
case "DESCRIBE": case "DESCRIBE":
if c.state != "STARTING" { if c.state != _CLIENT_STATE_STARTING {
c.writeResError(req, fmt.Errorf("client is in state '%s'", c.state)) c.writeResError(req, fmt.Errorf("client is in state '%d'", c.state))
return false return false
} }
@ -223,8 +234,8 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
return true return true
case "ANNOUNCE": case "ANNOUNCE":
if c.state != "STARTING" { if c.state != _CLIENT_STATE_STARTING {
c.writeResError(req, fmt.Errorf("client is in state '%s'", c.state)) c.writeResError(req, fmt.Errorf("client is in state '%d'", c.state))
return false return false
} }
@ -294,7 +305,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
c.p.publishers[path] = c c.p.publishers[path] = c
c.streamSdpText = req.Content c.streamSdpText = req.Content
c.streamSdpParsed = sdpParsed c.streamSdpParsed = sdpParsed
c.state = "ANNOUNCE" c.state = _CLIENT_STATE_ANNOUNCE
return nil return nil
}() }()
if err != nil { if err != nil {
@ -327,7 +338,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
switch c.state { switch c.state {
// play // play
case "STARTING", "PRE_PLAY": case _CLIENT_STATE_STARTING, _CLIENT_STATE_PRE_PLAY:
// play via UDP // play via UDP
if func() bool { if func() bool {
_, ok := th["RTP/AVP"] _, ok := th["RTP/AVP"]
@ -387,7 +398,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
rtcpPort: rtcpPort, rtcpPort: rtcpPort,
}) })
c.state = "PRE_PLAY" c.state = _CLIENT_STATE_PRE_PLAY
return nil return nil
}() }()
if err != nil { if err != nil {
@ -454,7 +465,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
rtcpPort: 0, rtcpPort: 0,
}) })
c.state = "PRE_PLAY" c.state = _CLIENT_STATE_PRE_PLAY
return nil return nil
}() }()
if err != nil { if err != nil {
@ -485,7 +496,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
} }
// record // record
case "ANNOUNCE", "PRE_RECORD": case _CLIENT_STATE_ANNOUNCE, _CLIENT_STATE_PRE_RECORD:
if _, ok := th["mode=record"]; !ok { if _, ok := th["mode=record"]; !ok {
c.writeResError(req, fmt.Errorf("transport header does not contain mode=record")) c.writeResError(req, fmt.Errorf("transport header does not contain mode=record"))
return false return false
@ -544,7 +555,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
rtcpPort: rtcpPort, rtcpPort: rtcpPort,
}) })
c.state = "PRE_RECORD" c.state = _CLIENT_STATE_PRE_RECORD
return nil return nil
}() }()
if err != nil { if err != nil {
@ -611,7 +622,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
rtcpPort: 0, rtcpPort: 0,
}) })
c.state = "PRE_RECORD" c.state = _CLIENT_STATE_PRE_RECORD
return nil return nil
}() }()
if err != nil { if err != nil {
@ -640,13 +651,13 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
} }
default: default:
c.writeResError(req, fmt.Errorf("client is in state '%s'", c.state)) c.writeResError(req, fmt.Errorf("client is in state '%d'", c.state))
return false return false
} }
case "PLAY": case "PLAY":
if c.state != "PRE_PLAY" { if c.state != _CLIENT_STATE_PRE_PLAY {
c.writeResError(req, fmt.Errorf("client is in state '%s'", c.state)) c.writeResError(req, fmt.Errorf("client is in state '%d'", c.state))
return false return false
} }
@ -695,7 +706,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
}(), c.streamProtocol) }(), c.streamProtocol)
c.p.mutex.Lock() c.p.mutex.Lock()
c.state = "PLAY" c.state = _CLIENT_STATE_PLAY
c.p.mutex.Unlock() c.p.mutex.Unlock()
// when protocol is TCP, the RTSP connection becomes a RTP connection // when protocol is TCP, the RTSP connection becomes a RTP connection
@ -716,8 +727,8 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
return true return true
case "PAUSE": case "PAUSE":
if c.state != "PLAY" { if c.state != _CLIENT_STATE_PLAY {
c.writeResError(req, fmt.Errorf("client is in state '%s'", c.state)) c.writeResError(req, fmt.Errorf("client is in state '%d'", c.state))
return false return false
} }
@ -729,7 +740,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
c.log("paused") c.log("paused")
c.p.mutex.Lock() c.p.mutex.Lock()
c.state = "PRE_PLAY" c.state = _CLIENT_STATE_PRE_PLAY
c.p.mutex.Unlock() c.p.mutex.Unlock()
c.writeRes(&gortsplib.Response{ c.writeRes(&gortsplib.Response{
@ -743,8 +754,8 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
return true return true
case "RECORD": case "RECORD":
if c.state != "PRE_RECORD" { if c.state != _CLIENT_STATE_PRE_RECORD {
c.writeResError(req, fmt.Errorf("client is in state '%s'", c.state)) c.writeResError(req, fmt.Errorf("client is in state '%d'", c.state))
return false return false
} }
@ -778,7 +789,7 @@ func (c *client) handleRequest(req *gortsplib.Request) bool {
}) })
c.p.mutex.Lock() c.p.mutex.Lock()
c.state = "RECORD" c.state = _CLIENT_STATE_RECORD
c.p.mutex.Unlock() c.p.mutex.Unlock()
c.log("is publishing on path '%s', %d %s via %s", c.path, len(c.streamTracks), func() string { c.log("is publishing on path '%s', %d %s via %s", c.path, len(c.streamTracks), func() string {

2
main.go

@ -121,7 +121,7 @@ func (p *program) run() {
func (p *program) forwardTrack(path string, id int, flow trackFlow, frame []byte) { func (p *program) forwardTrack(path string, id int, flow trackFlow, frame []byte) {
for c := range p.clients { for c := range p.clients {
if c.path == path && c.state == "PLAY" { if c.path == path && c.state == _CLIENT_STATE_PLAY {
if c.streamProtocol == _STREAM_PROTOCOL_UDP { if c.streamProtocol == _STREAM_PROTOCOL_UDP {
if flow == _TRACK_FLOW_RTP { if flow == _TRACK_FLOW_RTP {
p.rtpl.nconn.WriteTo(frame, &net.UDPAddr{ p.rtpl.nconn.WriteTo(frame, &net.UDPAddr{

Loading…
Cancel
Save