|
|
|
@ -917,43 +917,20 @@ func (c *serverClient) runRecord(path string) {
@@ -917,43 +917,20 @@ func (c *serverClient) runRecord(path string) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if c.streamProtocol == gortsplib.StreamProtocolTcp { |
|
|
|
|
frame := &gortsplib.InterleavedFrame{} |
|
|
|
|
|
|
|
|
|
if c.streamProtocol == gortsplib.StreamProtocolUdp { |
|
|
|
|
readDone := make(chan error) |
|
|
|
|
go func() { |
|
|
|
|
for { |
|
|
|
|
frame.Content = c.readBuf.swap() |
|
|
|
|
frame.Content = frame.Content[:cap(frame.Content)] |
|
|
|
|
|
|
|
|
|
recv, err := c.conn.ReadFrameOrRequest(frame) |
|
|
|
|
req, err := c.conn.ReadRequest() |
|
|
|
|
if err != nil { |
|
|
|
|
readDone <- err |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch recvt := recv.(type) { |
|
|
|
|
case *gortsplib.InterleavedFrame: |
|
|
|
|
if frame.TrackId >= len(c.streamTracks) { |
|
|
|
|
c.log("ERR: invalid track id '%d'", frame.TrackId) |
|
|
|
|
readDone <- nil |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c.rtcpReceivers[frame.TrackId].OnFrame(frame.StreamType, frame.Content) |
|
|
|
|
c.p.events <- programEventClientFrameTcp{ |
|
|
|
|
c.path, |
|
|
|
|
frame.TrackId, |
|
|
|
|
frame.StreamType, |
|
|
|
|
frame.Content, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case *gortsplib.Request: |
|
|
|
|
ok := c.handleRequest(recvt) |
|
|
|
|
if !ok { |
|
|
|
|
readDone <- nil |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
ok := c.handleRequest(req) |
|
|
|
|
if !ok { |
|
|
|
|
readDone <- nil |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
@ -961,14 +938,14 @@ func (c *serverClient) runRecord(path string) {
@@ -961,14 +938,14 @@ func (c *serverClient) runRecord(path string) {
|
|
|
|
|
checkStreamTicker := time.NewTicker(clientCheckStreamInterval) |
|
|
|
|
receiverReportTicker := time.NewTicker(clientReceiverReportInterval) |
|
|
|
|
|
|
|
|
|
outer1: |
|
|
|
|
outer2: |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case err := <-readDone: |
|
|
|
|
if err != nil && err != io.EOF { |
|
|
|
|
c.log("ERR: %s", err) |
|
|
|
|
} |
|
|
|
|
break outer1 |
|
|
|
|
break outer2 |
|
|
|
|
|
|
|
|
|
case <-checkStreamTicker.C: |
|
|
|
|
for trackId := range c.streamTracks { |
|
|
|
@ -976,18 +953,21 @@ func (c *serverClient) runRecord(path string) {
@@ -976,18 +953,21 @@ func (c *serverClient) runRecord(path string) {
|
|
|
|
|
c.log("ERR: stream is dead") |
|
|
|
|
c.conn.NetConn().Close() |
|
|
|
|
<-readDone |
|
|
|
|
break outer1 |
|
|
|
|
break outer2 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case <-receiverReportTicker.C: |
|
|
|
|
for trackId := range c.streamTracks { |
|
|
|
|
frame := c.rtcpReceivers[trackId].Report() |
|
|
|
|
c.conn.WriteFrame(&gortsplib.InterleavedFrame{ |
|
|
|
|
TrackId: trackId, |
|
|
|
|
StreamType: gortsplib.StreamTypeRtcp, |
|
|
|
|
Content: frame, |
|
|
|
|
}) |
|
|
|
|
c.p.rtcpl.writeChan <- &udpAddrBufPair{ |
|
|
|
|
addr: &net.UDPAddr{ |
|
|
|
|
IP: c.ip(), |
|
|
|
|
Zone: c.zone(), |
|
|
|
|
Port: c.streamTracks[trackId].rtcpPort, |
|
|
|
|
}, |
|
|
|
|
buf: frame, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -996,61 +976,69 @@ func (c *serverClient) runRecord(path string) {
@@ -996,61 +976,69 @@ func (c *serverClient) runRecord(path string) {
|
|
|
|
|
receiverReportTicker.Stop() |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
frame := &gortsplib.InterleavedFrame{} |
|
|
|
|
|
|
|
|
|
readDone := make(chan error) |
|
|
|
|
go func() { |
|
|
|
|
for { |
|
|
|
|
req, err := c.conn.ReadRequest() |
|
|
|
|
frame.Content = c.readBuf.swap() |
|
|
|
|
frame.Content = frame.Content[:cap(frame.Content)] |
|
|
|
|
|
|
|
|
|
recv, err := c.conn.ReadFrameOrRequest(frame) |
|
|
|
|
if err != nil { |
|
|
|
|
readDone <- err |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ok := c.handleRequest(req) |
|
|
|
|
if !ok { |
|
|
|
|
readDone <- nil |
|
|
|
|
break |
|
|
|
|
switch recvt := recv.(type) { |
|
|
|
|
case *gortsplib.InterleavedFrame: |
|
|
|
|
if frame.TrackId >= len(c.streamTracks) { |
|
|
|
|
c.log("ERR: invalid track id '%d'", frame.TrackId) |
|
|
|
|
readDone <- nil |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c.rtcpReceivers[frame.TrackId].OnFrame(frame.StreamType, frame.Content) |
|
|
|
|
c.p.events <- programEventClientFrameTcp{ |
|
|
|
|
c.path, |
|
|
|
|
frame.TrackId, |
|
|
|
|
frame.StreamType, |
|
|
|
|
frame.Content, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case *gortsplib.Request: |
|
|
|
|
ok := c.handleRequest(recvt) |
|
|
|
|
if !ok { |
|
|
|
|
readDone <- nil |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
checkStreamTicker := time.NewTicker(clientCheckStreamInterval) |
|
|
|
|
receiverReportTicker := time.NewTicker(clientReceiverReportInterval) |
|
|
|
|
|
|
|
|
|
outer2: |
|
|
|
|
outer1: |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case err := <-readDone: |
|
|
|
|
if err != nil && err != io.EOF { |
|
|
|
|
c.log("ERR: %s", err) |
|
|
|
|
} |
|
|
|
|
break outer2 |
|
|
|
|
|
|
|
|
|
case <-checkStreamTicker.C: |
|
|
|
|
for trackId := range c.streamTracks { |
|
|
|
|
if time.Since(c.rtcpReceivers[trackId].LastFrameTime()) >= c.p.conf.ReadTimeout { |
|
|
|
|
c.log("ERR: stream is dead") |
|
|
|
|
c.conn.NetConn().Close() |
|
|
|
|
<-readDone |
|
|
|
|
break outer2 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break outer1 |
|
|
|
|
|
|
|
|
|
case <-receiverReportTicker.C: |
|
|
|
|
for trackId := range c.streamTracks { |
|
|
|
|
frame := c.rtcpReceivers[trackId].Report() |
|
|
|
|
c.p.rtcpl.writeChan <- &udpAddrBufPair{ |
|
|
|
|
addr: &net.UDPAddr{ |
|
|
|
|
IP: c.ip(), |
|
|
|
|
Zone: c.zone(), |
|
|
|
|
Port: c.streamTracks[trackId].rtcpPort, |
|
|
|
|
}, |
|
|
|
|
buf: frame, |
|
|
|
|
} |
|
|
|
|
c.conn.WriteFrame(&gortsplib.InterleavedFrame{ |
|
|
|
|
TrackId: trackId, |
|
|
|
|
StreamType: gortsplib.StreamTypeRtcp, |
|
|
|
|
Content: frame, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
checkStreamTicker.Stop() |
|
|
|
|
receiverReportTicker.Stop() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|