golanggohlsrtmpwebrtcmedia-serverobs-studiortcprtmp-proxyrtmp-serverrtprtsprtsp-proxyrtsp-relayrtsp-serversrtstreamingwebrtc-proxy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
2.3 KiB
124 lines
2.3 KiB
package main |
|
|
|
import ( |
|
"fmt" |
|
"log" |
|
"net" |
|
"os" |
|
"sync" |
|
|
|
"gopkg.in/alecthomas/kingpin.v2" |
|
) |
|
|
|
var Version string = "v0.0.0" |
|
|
|
type program struct { |
|
rtspPort int |
|
rtpPort int |
|
rtcpPort int |
|
mutex sync.RWMutex |
|
rtspl *rtspListener |
|
rtpl *udpListener |
|
rtcpl *udpListener |
|
clients map[*rtspClient]struct{} |
|
streamAuthor *rtspClient |
|
streamSdp []byte |
|
} |
|
|
|
func newProgram(rtspPort int, rtpPort int, rtcpPort int) (*program, error) { |
|
p := &program{ |
|
rtspPort: rtspPort, |
|
rtpPort: rtpPort, |
|
rtcpPort: rtcpPort, |
|
clients: make(map[*rtspClient]struct{}), |
|
} |
|
|
|
var err error |
|
|
|
p.rtpl, err = newUdpListener(rtpPort, "RTP", p.handleRtp) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
p.rtcpl, err = newUdpListener(rtcpPort, "RTCP", p.handleRtcp) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
p.rtspl, err = newRtspListener(p) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return p, nil |
|
} |
|
|
|
func (p *program) run() { |
|
go p.rtpl.run() |
|
go p.rtcpl.run() |
|
go p.rtspl.run() |
|
|
|
infty := make(chan struct{}) |
|
<-infty |
|
} |
|
|
|
func (p *program) handleRtp(frame []byte) { |
|
p.mutex.RLock() |
|
defer p.mutex.RUnlock() |
|
|
|
for c := range p.clients { |
|
if c.state == "PLAY" { |
|
if c.rtpProto == "udp" { |
|
p.rtpl.nconn.WriteTo(frame, &net.UDPAddr{ |
|
IP: c.IP, |
|
Port: c.rtpPort, |
|
}) |
|
} else { |
|
c.rconn.WriteInterleavedFrame(frame) |
|
} |
|
} |
|
} |
|
} |
|
|
|
func (p *program) handleRtcp(frame []byte) { |
|
p.mutex.RLock() |
|
defer p.mutex.RUnlock() |
|
|
|
for c := range p.clients { |
|
if c.state == "PLAY" { |
|
if c.rtpProto == "udp" { |
|
p.rtcpl.nconn.WriteTo(frame, &net.UDPAddr{ |
|
IP: c.IP, |
|
Port: c.rtcpPort, |
|
}) |
|
} else { |
|
c.rconn.WriteInterleavedFrame(frame) |
|
} |
|
} |
|
} |
|
} |
|
|
|
func main() { |
|
kingpin.CommandLine.Help = "rtsp-simple-server " + Version + "\n\n" + |
|
"RTSP server." |
|
|
|
version := kingpin.Flag("version", "print rtsp-simple-server version").Bool() |
|
|
|
rtspPort := kingpin.Flag("rtsp-port", "port of the RTSP TCP listener").Default("8554").Int() |
|
rtpPort := kingpin.Flag("rtp-port", "port of the RTP UDP listener").Default("8000").Int() |
|
rtcpPort := kingpin.Flag("rtcp-port", "port of the RTCP UDP listener").Default("8001").Int() |
|
|
|
kingpin.Parse() |
|
|
|
if *version == true { |
|
fmt.Println("rtsp-simple-server " + Version) |
|
os.Exit(0) |
|
} |
|
|
|
p, err := newProgram(*rtspPort, *rtpPort, *rtcpPort) |
|
if err != nil { |
|
log.Fatal("ERR: ", err) |
|
} |
|
|
|
p.run() |
|
}
|
|
|