improve performance

This commit is contained in:
aler9
2020-09-20 14:48:37 +02:00
parent 81b5754b0b
commit e34b7d9326
4 changed files with 53 additions and 25 deletions

View File

@@ -72,7 +72,7 @@ type ConnClient struct {
udpLastFrameTimes map[int]*int64 udpLastFrameTimes map[int]*int64
udpRtpListeners map[int]*connClientUDPListener udpRtpListeners map[int]*connClientUDPListener
udpRtcpListeners map[int]*connClientUDPListener udpRtcpListeners map[int]*connClientUDPListener
tcpFrameReadBuf *MultiBuffer tcpFrames *multiFrame
playing bool playing bool
receiverReportTerminate chan struct{} receiverReportTerminate chan struct{}
@@ -150,9 +150,7 @@ func (c *ConnClient) NetConn() net.Conn {
// ReadFrame reads an InterleavedFrame. // ReadFrame reads an InterleavedFrame.
func (c *ConnClient) ReadFrame() (*InterleavedFrame, error) { func (c *ConnClient) ReadFrame() (*InterleavedFrame, error) {
c.nconn.SetReadDeadline(time.Now().Add(c.conf.ReadTimeout)) c.nconn.SetReadDeadline(time.Now().Add(c.conf.ReadTimeout))
frame := &InterleavedFrame{ frame := c.tcpFrames.next()
Content: c.tcpFrameReadBuf.Next(),
}
err := frame.Read(c.br) err := frame.Read(c.br)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -172,9 +170,7 @@ func (c *ConnClient) readFrameOrResponse() (interface{}, error) {
c.br.UnreadByte() c.br.UnreadByte()
if b == interleavedFrameMagicByte { if b == interleavedFrameMagicByte {
frame := &InterleavedFrame{ frame := c.tcpFrames.next()
Content: c.tcpFrameReadBuf.Next(),
}
err := frame.Read(c.br) err := frame.Read(c.br)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -610,7 +606,7 @@ func (c *ConnClient) Play(u *url.URL) (*Response, error) {
return nil, err return nil, err
} }
c.tcpFrameReadBuf = NewMultiBuffer(c.conf.ReadBufferCount, clientTCPFrameReadBufferSize) c.tcpFrames = newMultiFrame(c.conf.ReadBufferCount, clientTCPFrameReadBufferSize)
// v4lrtspserver sends frames before the response. // v4lrtspserver sends frames before the response.
// ignore them and wait for the response. // ignore them and wait for the response.

View File

@@ -36,7 +36,7 @@ type ConnServer struct {
conf ConnServerConf conf ConnServerConf
br *bufio.Reader br *bufio.Reader
bw *bufio.Writer bw *bufio.Writer
tcpFrameReadBuf *MultiBuffer tcpFrames *multiFrame
} }
// NewConnServer allocates a ConnServer. // NewConnServer allocates a ConnServer.
@@ -55,7 +55,7 @@ func NewConnServer(conf ConnServerConf) *ConnServer {
conf: conf, conf: conf,
br: bufio.NewReaderSize(conf.Conn, serverReadBufferSize), br: bufio.NewReaderSize(conf.Conn, serverReadBufferSize),
bw: bufio.NewWriterSize(conf.Conn, serverWriteBufferSize), bw: bufio.NewWriterSize(conf.Conn, serverWriteBufferSize),
tcpFrameReadBuf: NewMultiBuffer(conf.ReadBufferCount, clientTCPFrameReadBufferSize), tcpFrames: newMultiFrame(conf.ReadBufferCount, clientTCPFrameReadBufferSize),
} }
} }
@@ -88,9 +88,7 @@ func (s *ConnServer) ReadFrameOrRequest(timeout bool) (interface{}, error) {
s.br.UnreadByte() s.br.UnreadByte()
if b == interleavedFrameMagicByte { if b == interleavedFrameMagicByte {
frame := &InterleavedFrame{ frame := s.tcpFrames.next()
Content: s.tcpFrameReadBuf.Next(),
}
err := frame.Read(s.br) err := frame.Read(s.br)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -3,8 +3,9 @@ package gortsplib
// MultiBuffer implements software multi buffering, that allows to reuse // MultiBuffer implements software multi buffering, that allows to reuse
// existing buffers without creating new ones, increasing performance. // existing buffers without creating new ones, increasing performance.
type MultiBuffer struct { type MultiBuffer struct {
count int
buffers [][]byte buffers [][]byte
curBuf int cur int
} }
// NewMultiBuffer allocates a MultiBuffer. // NewMultiBuffer allocates a MultiBuffer.
@@ -15,16 +16,49 @@ func NewMultiBuffer(count int, size int) *MultiBuffer {
} }
return &MultiBuffer{ return &MultiBuffer{
count: count,
buffers: buffers, buffers: buffers,
} }
} }
// Next gets the current buffer and sets the next buffer as the current one. // Next gets the current buffer and sets the next buffer as the current one.
func (mb *MultiBuffer) Next() []byte { func (mb *MultiBuffer) Next() []byte {
ret := mb.buffers[mb.curBuf] ret := mb.buffers[mb.cur]
mb.curBuf += 1 mb.cur += 1
if mb.curBuf >= len(mb.buffers) { if mb.cur >= mb.count {
mb.curBuf = 0 mb.cur = 0
} }
return ret return ret
} }
type multiFrame struct {
count int
frames []*InterleavedFrame
cur int
}
func newMultiFrame(count int, bufsize int) *multiFrame {
frames := make([]*InterleavedFrame, count)
for i := 0; i < count; i++ {
frames[i] = &InterleavedFrame{
Content: make([]byte, 0, bufsize),
}
}
return &multiFrame{
count: count,
frames: frames,
}
}
func (mf *multiFrame) next() *InterleavedFrame {
ret := mf.frames[mf.cur]
mf.cur += 1
if mf.cur >= mf.count {
mf.cur = 0
}
ret.Content = ret.Content[:cap(ret.Content)]
return ret
}

View File

@@ -56,7 +56,7 @@ func (rr *RtcpReceiver) OnFrame(streamType StreamType, buf []byte) {
} else { } else {
// we can afford to unmarshal all RTCP frames // we can afford to unmarshal all RTCP frames
// since they are sent with a frequency much lower than the one of the RTP frames // since they are sent with a frequency much lower than the one of RTP frames
frames, err := rtcp.Unmarshal(buf) frames, err := rtcp.Unmarshal(buf)
if err == nil { if err == nil {
for _, frame := range frames { for _, frame := range frames {