mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-09-26 19:51:26 +08:00
fix OPTIONS method; reorder methods
This commit is contained in:
@@ -8,7 +8,10 @@ _rtsp-simple-server_ is a simple, ready-to-use and zero-dependency RTSP server,
|
||||
|
||||
This software was developed with the aim of simulating a live camera feed for debugging purposes, and therefore to use files instead of real streams. Another reason for the development was the deprecation of _FFserver_, the component of the FFmpeg project that allowed to create a RTSP server with _FFmpeg_ (but this server can be used with any software that supports RTSP).
|
||||
|
||||
It actually supports *one* publisher, while readers can be more than one.
|
||||
Features:
|
||||
* Supports reading and publishing streams
|
||||
* Supports one publisher at once, while readers can be more than one.
|
||||
* Supports reading via UDP and TCP
|
||||
|
||||
|
||||
<br />
|
||||
|
102
rtsp_client.go
102
rtsp_client.go
@@ -104,9 +104,11 @@ func (c *rtspClient) run(wg sync.WaitGroup) {
|
||||
"CSeq": cseq,
|
||||
"Public": strings.Join([]string{
|
||||
"DESCRIBE",
|
||||
"ANNOUNCE",
|
||||
"SETUP",
|
||||
"PLAY",
|
||||
"PAUSE",
|
||||
"RECORD",
|
||||
"TEARDOWN",
|
||||
}, ", "),
|
||||
},
|
||||
@@ -152,6 +154,56 @@ func (c *rtspClient) run(wg sync.WaitGroup) {
|
||||
return
|
||||
}
|
||||
|
||||
case "ANNOUNCE":
|
||||
if c.state != "STARTING" {
|
||||
c.log("ERR: client is in state '%s'", c.state)
|
||||
return
|
||||
}
|
||||
|
||||
ct, ok := req.Headers["Content-Type"]
|
||||
if !ok {
|
||||
c.log("ERR: Content-Type header missing")
|
||||
return
|
||||
}
|
||||
|
||||
if ct != "application/sdp" {
|
||||
c.log("ERR: unsupported Content-Type '%s'", ct)
|
||||
return
|
||||
}
|
||||
|
||||
err := func() error {
|
||||
c.p.mutex.Lock()
|
||||
defer c.p.mutex.Unlock()
|
||||
|
||||
if c.p.streamAuthor != nil {
|
||||
return fmt.Errorf("another client is already streaming")
|
||||
}
|
||||
|
||||
c.p.streamAuthor = c
|
||||
c.p.streamSdp = req.Content
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = c.rconn.WriteResponse(&rtsp.Response{
|
||||
StatusCode: 200,
|
||||
Status: "OK",
|
||||
Headers: map[string]string{
|
||||
"CSeq": cseq,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.p.mutex.Lock()
|
||||
c.state = "ANNOUNCE"
|
||||
c.p.mutex.Unlock()
|
||||
|
||||
case "SETUP":
|
||||
transport, ok := req.Headers["Transport"]
|
||||
if !ok {
|
||||
@@ -354,56 +406,6 @@ func (c *rtspClient) run(wg sync.WaitGroup) {
|
||||
c.state = "RECORD"
|
||||
c.p.mutex.Unlock()
|
||||
|
||||
case "ANNOUNCE":
|
||||
if c.state != "STARTING" {
|
||||
c.log("ERR: client is in state '%s'", c.state)
|
||||
return
|
||||
}
|
||||
|
||||
ct, ok := req.Headers["Content-Type"]
|
||||
if !ok {
|
||||
c.log("ERR: Content-Type header missing")
|
||||
return
|
||||
}
|
||||
|
||||
if ct != "application/sdp" {
|
||||
c.log("ERR: unsupported Content-Type '%s'", ct)
|
||||
return
|
||||
}
|
||||
|
||||
err := func() error {
|
||||
c.p.mutex.Lock()
|
||||
defer c.p.mutex.Unlock()
|
||||
|
||||
if c.p.streamAuthor != nil {
|
||||
return fmt.Errorf("another client is already streaming")
|
||||
}
|
||||
|
||||
c.p.streamAuthor = c
|
||||
c.p.streamSdp = req.Content
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = c.rconn.WriteResponse(&rtsp.Response{
|
||||
StatusCode: 200,
|
||||
Status: "OK",
|
||||
Headers: map[string]string{
|
||||
"CSeq": cseq,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.p.mutex.Lock()
|
||||
c.state = "ANNOUNCE"
|
||||
c.p.mutex.Unlock()
|
||||
|
||||
case "TEARDOWN":
|
||||
return
|
||||
|
||||
|
Reference in New Issue
Block a user