mirror of
https://github.com/aler9/gortsplib
synced 2025-10-04 23:02:45 +08:00
normalize names
This commit is contained in:
@@ -348,14 +348,14 @@ func TestClientDialPublishSerial(t *testing.T) {
|
|||||||
buf := make([]byte, 2048)
|
buf := make([]byte, 2048)
|
||||||
n, _, err := pc.ReadFrom(buf)
|
n, _, err := pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
|
||||||
n, _, err = pc.ReadFrom(buf)
|
n, _, err = pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -446,7 +446,7 @@ func TestClientDialPublishParallel(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -524,7 +524,7 @@ func TestClientDialPublishPauseSerial(t *testing.T) {
|
|||||||
|
|
||||||
n, _, err := pc.ReadFrom(buf)
|
n, _, err := pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = conn.Pause()
|
_, err = conn.Pause()
|
||||||
@@ -532,7 +532,7 @@ func TestClientDialPublishPauseSerial(t *testing.T) {
|
|||||||
|
|
||||||
n, _, err = pc.ReadFrom(buf)
|
n, _, err = pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
_, err = conn.Record()
|
_, err = conn.Record()
|
||||||
@@ -540,7 +540,7 @@ func TestClientDialPublishPauseSerial(t *testing.T) {
|
|||||||
|
|
||||||
n, _, err = pc.ReadFrom(buf)
|
n, _, err = pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -600,7 +600,7 @@ func TestClientDialPublishPauseParallel(t *testing.T) {
|
|||||||
n, _, err := pc.ReadFrom(buf)
|
n, _, err := pc.ReadFrom(buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = conn.WriteFrame(track.ID, StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, StreamTypeRTP, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@@ -76,18 +76,18 @@ type ClientConn struct {
|
|||||||
streamURL *base.URL
|
streamURL *base.URL
|
||||||
streamProtocol *StreamProtocol
|
streamProtocol *StreamProtocol
|
||||||
tracks Tracks
|
tracks Tracks
|
||||||
udpRtpListeners map[int]*clientConnUDPListener
|
udpRTPListeners map[int]*clientConnUDPListener
|
||||||
udpRtcpListeners map[int]*clientConnUDPListener
|
udpRTCPListeners map[int]*clientConnUDPListener
|
||||||
getParameterSupported bool
|
getParameterSupported bool
|
||||||
|
|
||||||
// read only
|
// read only
|
||||||
rtcpReceivers map[int]*rtcpreceiver.RtcpReceiver
|
rtcpReceivers map[int]*rtcpreceiver.RTCPReceiver
|
||||||
udpLastFrameTimes map[int]*int64
|
udpLastFrameTimes map[int]*int64
|
||||||
tcpFrameBuffer *multibuffer.MultiBuffer
|
tcpFrameBuffer *multibuffer.MultiBuffer
|
||||||
readCB func(int, StreamType, []byte)
|
readCB func(int, StreamType, []byte)
|
||||||
|
|
||||||
// publish only
|
// publish only
|
||||||
rtcpSenders map[int]*rtcpsender.RtcpSender
|
rtcpSenders map[int]*rtcpsender.RTCPSender
|
||||||
publishError error
|
publishError error
|
||||||
publishWriteMutex sync.RWMutex
|
publishWriteMutex sync.RWMutex
|
||||||
publishOpen bool
|
publishOpen bool
|
||||||
@@ -150,12 +150,12 @@ func newClientConn(conf ClientConf, scheme string, host string) (*ClientConn, er
|
|||||||
isTLS: (scheme == "rtsps"),
|
isTLS: (scheme == "rtsps"),
|
||||||
br: bufio.NewReaderSize(conn, clientReadBufferSize),
|
br: bufio.NewReaderSize(conn, clientReadBufferSize),
|
||||||
bw: bufio.NewWriterSize(conn, clientWriteBufferSize),
|
bw: bufio.NewWriterSize(conn, clientWriteBufferSize),
|
||||||
udpRtpListeners: make(map[int]*clientConnUDPListener),
|
udpRTPListeners: make(map[int]*clientConnUDPListener),
|
||||||
udpRtcpListeners: make(map[int]*clientConnUDPListener),
|
udpRTCPListeners: make(map[int]*clientConnUDPListener),
|
||||||
rtcpReceivers: make(map[int]*rtcpreceiver.RtcpReceiver),
|
rtcpReceivers: make(map[int]*rtcpreceiver.RTCPReceiver),
|
||||||
udpLastFrameTimes: make(map[int]*int64),
|
udpLastFrameTimes: make(map[int]*int64),
|
||||||
tcpFrameBuffer: multibuffer.New(conf.ReadBufferCount, clientTCPFrameReadBufferSize),
|
tcpFrameBuffer: multibuffer.New(conf.ReadBufferCount, clientTCPFrameReadBufferSize),
|
||||||
rtcpSenders: make(map[int]*rtcpsender.RtcpSender),
|
rtcpSenders: make(map[int]*rtcpsender.RTCPSender),
|
||||||
publishError: fmt.Errorf("not running"),
|
publishError: fmt.Errorf("not running"),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -173,11 +173,11 @@ func (c *ClientConn) Close() error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range c.udpRtpListeners {
|
for _, l := range c.udpRTPListeners {
|
||||||
l.close()
|
l.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range c.udpRtcpListeners {
|
for _, l := range c.udpRTCPListeners {
|
||||||
l.close()
|
l.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,15 +634,15 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
rtpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
rtpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
||||||
rtpListener.remotePort = (*thRes.ServerPorts)[0]
|
rtpListener.remotePort = (*thRes.ServerPorts)[0]
|
||||||
rtpListener.trackID = track.ID
|
rtpListener.trackID = track.ID
|
||||||
rtpListener.streamType = StreamTypeRtp
|
rtpListener.streamType = StreamTypeRTP
|
||||||
c.udpRtpListeners[track.ID] = rtpListener
|
c.udpRTPListeners[track.ID] = rtpListener
|
||||||
|
|
||||||
rtcpListener.remoteIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
|
rtcpListener.remoteIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
|
||||||
rtcpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
rtcpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
|
||||||
rtcpListener.remotePort = (*thRes.ServerPorts)[1]
|
rtcpListener.remotePort = (*thRes.ServerPorts)[1]
|
||||||
rtcpListener.trackID = track.ID
|
rtcpListener.trackID = track.ID
|
||||||
rtcpListener.streamType = StreamTypeRtcp
|
rtcpListener.streamType = StreamTypeRTCP
|
||||||
c.udpRtcpListeners[track.ID] = rtcpListener
|
c.udpRTCPListeners[track.ID] = rtcpListener
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == headers.TransportModePlay {
|
if mode == headers.TransportModePlay {
|
||||||
|
@@ -129,7 +129,7 @@ func (c *ClientConn) backgroundRecordUDP() {
|
|||||||
for trackID := range c.rtcpSenders {
|
for trackID := range c.rtcpSenders {
|
||||||
r := c.rtcpSenders[trackID].Report(now)
|
r := c.rtcpSenders[trackID].Report(now)
|
||||||
if r != nil {
|
if r != nil {
|
||||||
c.udpRtcpListeners[trackID].write(r)
|
c.udpRTCPListeners[trackID].write(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.publishWriteMutex.Unlock()
|
c.publishWriteMutex.Unlock()
|
||||||
@@ -167,7 +167,7 @@ func (c *ClientConn) backgroundRecordTCP() {
|
|||||||
c.nconn.SetWriteDeadline(time.Now().Add(c.conf.WriteTimeout))
|
c.nconn.SetWriteDeadline(time.Now().Add(c.conf.WriteTimeout))
|
||||||
frame := base.InterleavedFrame{
|
frame := base.InterleavedFrame{
|
||||||
TrackID: trackID,
|
TrackID: trackID,
|
||||||
StreamType: StreamTypeRtcp,
|
StreamType: StreamTypeRTCP,
|
||||||
Content: r,
|
Content: r,
|
||||||
}
|
}
|
||||||
frame.Write(c.bw)
|
frame.Write(c.bw)
|
||||||
@@ -193,10 +193,10 @@ func (c *ClientConn) WriteFrame(trackID int, streamType StreamType, payload []by
|
|||||||
c.rtcpSenders[trackID].ProcessFrame(now, streamType, payload)
|
c.rtcpSenders[trackID].ProcessFrame(now, streamType, payload)
|
||||||
|
|
||||||
if *c.streamProtocol == StreamProtocolUDP {
|
if *c.streamProtocol == StreamProtocolUDP {
|
||||||
if streamType == StreamTypeRtp {
|
if streamType == StreamTypeRTP {
|
||||||
return c.udpRtpListeners[trackID].write(payload)
|
return c.udpRTPListeners[trackID].write(payload)
|
||||||
}
|
}
|
||||||
return c.udpRtcpListeners[trackID].write(payload)
|
return c.udpRTCPListeners[trackID].write(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.nconn.SetWriteDeadline(now.Add(c.conf.WriteTimeout))
|
c.nconn.SetWriteDeadline(now.Add(c.conf.WriteTimeout))
|
||||||
|
@@ -39,26 +39,26 @@ func (c *ClientConn) backgroundPlayUDP(done chan error) {
|
|||||||
var returnError error
|
var returnError error
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
for trackID := range c.udpRtpListeners {
|
for trackID := range c.udpRTPListeners {
|
||||||
c.udpRtpListeners[trackID].stop()
|
c.udpRTPListeners[trackID].stop()
|
||||||
c.udpRtcpListeners[trackID].stop()
|
c.udpRTCPListeners[trackID].stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
done <- returnError
|
done <- returnError
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// open the firewall by sending packets to the counterpart
|
// open the firewall by sending packets to the counterpart
|
||||||
for trackID := range c.udpRtpListeners {
|
for trackID := range c.udpRTPListeners {
|
||||||
c.udpRtpListeners[trackID].write(
|
c.udpRTPListeners[trackID].write(
|
||||||
[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
|
|
||||||
c.udpRtcpListeners[trackID].write(
|
c.udpRTCPListeners[trackID].write(
|
||||||
[]byte{0x80, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00})
|
[]byte{0x80, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
|
|
||||||
for trackID := range c.udpRtpListeners {
|
for trackID := range c.udpRTPListeners {
|
||||||
c.udpRtpListeners[trackID].start()
|
c.udpRTPListeners[trackID].start()
|
||||||
c.udpRtcpListeners[trackID].start()
|
c.udpRTCPListeners[trackID].start()
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable deadline
|
// disable deadline
|
||||||
@@ -97,7 +97,7 @@ func (c *ClientConn) backgroundPlayUDP(done chan error) {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
for trackID := range c.rtcpReceivers {
|
for trackID := range c.rtcpReceivers {
|
||||||
r := c.rtcpReceivers[trackID].Report(now)
|
r := c.rtcpReceivers[trackID].Report(now)
|
||||||
c.udpRtcpListeners[trackID].write(r)
|
c.udpRTCPListeners[trackID].write(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-keepaliveTicker.C:
|
case <-keepaliveTicker.C:
|
||||||
@@ -195,7 +195,7 @@ func (c *ClientConn) backgroundPlayTCP(done chan error) {
|
|||||||
c.nconn.SetWriteDeadline(time.Now().Add(c.conf.WriteTimeout))
|
c.nconn.SetWriteDeadline(time.Now().Add(c.conf.WriteTimeout))
|
||||||
frame := base.InterleavedFrame{
|
frame := base.InterleavedFrame{
|
||||||
TrackID: trackID,
|
TrackID: trackID,
|
||||||
StreamType: StreamTypeRtcp,
|
StreamType: StreamTypeRTCP,
|
||||||
Content: r,
|
Content: r,
|
||||||
}
|
}
|
||||||
frame.Write(c.bw)
|
frame.Write(c.bw)
|
||||||
|
8
defs.go
8
defs.go
@@ -19,9 +19,9 @@ const (
|
|||||||
type StreamType = base.StreamType
|
type StreamType = base.StreamType
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// StreamTypeRtp means that the stream contains RTP packets
|
// StreamTypeRTP means that the stream contains RTP packets
|
||||||
StreamTypeRtp StreamType = base.StreamTypeRtp
|
StreamTypeRTP StreamType = base.StreamTypeRTP
|
||||||
|
|
||||||
// StreamTypeRtcp means that the stream contains RTCP packets
|
// StreamTypeRTCP means that the stream contains RTCP packets
|
||||||
StreamTypeRtcp StreamType = base.StreamTypeRtcp
|
StreamTypeRTCP StreamType = base.StreamTypeRTCP
|
||||||
)
|
)
|
||||||
|
@@ -70,7 +70,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write track frames
|
// write track frames
|
||||||
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRTP, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -66,7 +66,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write track frames
|
// write track frames
|
||||||
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRTP, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@@ -58,7 +58,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write track frames
|
// write track frames
|
||||||
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRtp, buf[:n])
|
err = conn.WriteFrame(track.ID, gortsplib.StreamTypeRTP, buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -50,20 +50,20 @@ func (sc StreamDelivery) String() string {
|
|||||||
type StreamType int
|
type StreamType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// StreamTypeRtp means that the stream contains RTP packets
|
// StreamTypeRTP means that the stream contains RTP packets
|
||||||
StreamTypeRtp StreamType = iota
|
StreamTypeRTP StreamType = iota
|
||||||
|
|
||||||
// StreamTypeRtcp means that the stream contains RTCP packets
|
// StreamTypeRTCP means that the stream contains RTCP packets
|
||||||
StreamTypeRtcp
|
StreamTypeRTCP
|
||||||
)
|
)
|
||||||
|
|
||||||
// String implements fmt.Stringer
|
// String implements fmt.Stringer
|
||||||
func (st StreamType) String() string {
|
func (st StreamType) String() string {
|
||||||
switch st {
|
switch st {
|
||||||
case StreamTypeRtp:
|
case StreamTypeRTP:
|
||||||
return "RTP"
|
return "RTP"
|
||||||
|
|
||||||
case StreamTypeRtcp:
|
case StreamTypeRTCP:
|
||||||
return "RTCP"
|
return "RTCP"
|
||||||
}
|
}
|
||||||
return "unknown"
|
return "unknown"
|
||||||
|
@@ -92,9 +92,9 @@ func (f *InterleavedFrame) Read(br *bufio.Reader) error {
|
|||||||
channel := header[1]
|
channel := header[1]
|
||||||
f.TrackID, f.StreamType = func() (int, StreamType) {
|
f.TrackID, f.StreamType = func() (int, StreamType) {
|
||||||
if (channel % 2) == 0 {
|
if (channel % 2) == 0 {
|
||||||
return int(channel / 2), StreamTypeRtp
|
return int(channel / 2), StreamTypeRTP
|
||||||
}
|
}
|
||||||
return int((channel - 1) / 2), StreamTypeRtcp
|
return int((channel - 1) / 2), StreamTypeRTCP
|
||||||
}()
|
}()
|
||||||
|
|
||||||
f.Content = f.Content[:framelen]
|
f.Content = f.Content[:framelen]
|
||||||
@@ -110,7 +110,7 @@ func (f *InterleavedFrame) Read(br *bufio.Reader) error {
|
|||||||
func (f InterleavedFrame) Write(bw *bufio.Writer) error {
|
func (f InterleavedFrame) Write(bw *bufio.Writer) error {
|
||||||
// convert TrackID and StreamType into channel
|
// convert TrackID and StreamType into channel
|
||||||
channel := func() uint8 {
|
channel := func() uint8 {
|
||||||
if f.StreamType == StreamTypeRtp {
|
if f.StreamType == StreamTypeRTP {
|
||||||
return uint8(f.TrackID * 2)
|
return uint8(f.TrackID * 2)
|
||||||
}
|
}
|
||||||
return uint8((f.TrackID * 2) + 1)
|
return uint8((f.TrackID * 2) + 1)
|
||||||
|
@@ -11,18 +11,18 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RtcpReceiver is a utility to generate RTCP receiver reports.
|
// RTCPReceiver is a utility to generate RTCP receiver reports.
|
||||||
type RtcpReceiver struct {
|
type RTCPReceiver struct {
|
||||||
receiverSSRC uint32
|
receiverSSRC uint32
|
||||||
clockRate float64
|
clockRate float64
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
|
|
||||||
// data from rtp packets
|
// data from rtp packets
|
||||||
firstRtpReceived bool
|
firstRTPReceived bool
|
||||||
sequenceNumberCycles uint16
|
sequenceNumberCycles uint16
|
||||||
lastSequenceNumber uint16
|
lastSequenceNumber uint16
|
||||||
lastRtpTimeRtp uint32
|
lastRTPTimeRTP uint32
|
||||||
lastRtpTimeTime time.Time
|
lastRTPTimeTime time.Time
|
||||||
totalLost uint32
|
totalLost uint32
|
||||||
totalLostSinceReport uint32
|
totalLostSinceReport uint32
|
||||||
totalSinceReport uint32
|
totalSinceReport uint32
|
||||||
@@ -34,9 +34,9 @@ type RtcpReceiver struct {
|
|||||||
lastSenderReportTime time.Time
|
lastSenderReportTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a RtcpReceiver.
|
// New allocates a RTCPReceiver.
|
||||||
func New(receiverSSRC *uint32, clockRate int) *RtcpReceiver {
|
func New(receiverSSRC *uint32, clockRate int) *RTCPReceiver {
|
||||||
return &RtcpReceiver{
|
return &RTCPReceiver{
|
||||||
receiverSSRC: func() uint32 {
|
receiverSSRC: func() uint32 {
|
||||||
if receiverSSRC == nil {
|
if receiverSSRC == nil {
|
||||||
return rand.Uint32()
|
return rand.Uint32()
|
||||||
@@ -48,23 +48,23 @@ func New(receiverSSRC *uint32, clockRate int) *RtcpReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ProcessFrame extracts the needed data from RTP or RTCP frames.
|
// ProcessFrame extracts the needed data from RTP or RTCP frames.
|
||||||
func (rr *RtcpReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, buf []byte) {
|
func (rr *RTCPReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, buf []byte) {
|
||||||
rr.mutex.Lock()
|
rr.mutex.Lock()
|
||||||
defer rr.mutex.Unlock()
|
defer rr.mutex.Unlock()
|
||||||
|
|
||||||
if streamType == base.StreamTypeRtp {
|
if streamType == base.StreamTypeRTP {
|
||||||
// do not parse the entire packet, extract only the fields we need
|
// do not parse the entire packet, extract only the fields we need
|
||||||
if len(buf) >= 8 {
|
if len(buf) >= 8 {
|
||||||
sequenceNumber := uint16(buf[2])<<8 | uint16(buf[3])
|
sequenceNumber := uint16(buf[2])<<8 | uint16(buf[3])
|
||||||
rtpTime := uint32(buf[4])<<24 | uint32(buf[5])<<16 | uint32(buf[6])<<8 | uint32(buf[7])
|
rtpTime := uint32(buf[4])<<24 | uint32(buf[5])<<16 | uint32(buf[6])<<8 | uint32(buf[7])
|
||||||
|
|
||||||
// first frame
|
// first frame
|
||||||
if !rr.firstRtpReceived {
|
if !rr.firstRTPReceived {
|
||||||
rr.firstRtpReceived = true
|
rr.firstRTPReceived = true
|
||||||
rr.totalSinceReport = 1
|
rr.totalSinceReport = 1
|
||||||
rr.lastSequenceNumber = sequenceNumber
|
rr.lastSequenceNumber = sequenceNumber
|
||||||
rr.lastRtpTimeRtp = rtpTime
|
rr.lastRTPTimeRTP = rtpTime
|
||||||
rr.lastRtpTimeTime = ts
|
rr.lastRTPTimeTime = ts
|
||||||
|
|
||||||
// subsequent frames
|
// subsequent frames
|
||||||
} else {
|
} else {
|
||||||
@@ -93,8 +93,8 @@ func (rr *RtcpReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, b
|
|||||||
|
|
||||||
// compute jitter
|
// compute jitter
|
||||||
// https://tools.ietf.org/html/rfc3550#page-39
|
// https://tools.ietf.org/html/rfc3550#page-39
|
||||||
D := ts.Sub(rr.lastRtpTimeTime).Seconds()*rr.clockRate -
|
D := ts.Sub(rr.lastRTPTimeTime).Seconds()*rr.clockRate -
|
||||||
(float64(rtpTime) - float64(rr.lastRtpTimeRtp))
|
(float64(rtpTime) - float64(rr.lastRTPTimeRTP))
|
||||||
if D < 0 {
|
if D < 0 {
|
||||||
D = -D
|
D = -D
|
||||||
}
|
}
|
||||||
@@ -102,8 +102,8 @@ func (rr *RtcpReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, b
|
|||||||
|
|
||||||
rr.totalSinceReport += uint32(uint16(diff))
|
rr.totalSinceReport += uint32(uint16(diff))
|
||||||
rr.lastSequenceNumber = sequenceNumber
|
rr.lastSequenceNumber = sequenceNumber
|
||||||
rr.lastRtpTimeRtp = rtpTime
|
rr.lastRTPTimeRTP = rtpTime
|
||||||
rr.lastRtpTimeTime = ts
|
rr.lastRTPTimeTime = ts
|
||||||
}
|
}
|
||||||
// ignore invalid frames (diff = 0) or reordered frames (diff < 0)
|
// ignore invalid frames (diff = 0) or reordered frames (diff < 0)
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ func (rr *RtcpReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Report generates a RTCP receiver report.
|
// Report generates a RTCP receiver report.
|
||||||
func (rr *RtcpReceiver) Report(ts time.Time) []byte {
|
func (rr *RTCPReceiver) Report(ts time.Time) []byte {
|
||||||
rr.mutex.Lock()
|
rr.mutex.Lock()
|
||||||
defer rr.mutex.Unlock()
|
defer rr.mutex.Unlock()
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRtcpReceiverBase(t *testing.T) {
|
func TestRTCPReceiverBase(t *testing.T) {
|
||||||
v := uint32(0x65f83afb)
|
v := uint32(0x65f83afb)
|
||||||
rr := New(&v, 90000)
|
rr := New(&v, 90000)
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ func TestRtcpReceiverBase(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := srPkt.Marshal()
|
byts, _ := srPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtcp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTCP, byts)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -39,7 +39,7 @@ func TestRtcpReceiverBase(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -54,7 +54,7 @@ func TestRtcpReceiverBase(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 21, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 21, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.ReceiverReport{
|
expectedPkt := rtcp.ReceiverReport{
|
||||||
SSRC: 0x65f83afb,
|
SSRC: 0x65f83afb,
|
||||||
@@ -72,7 +72,7 @@ func TestRtcpReceiverBase(t *testing.T) {
|
|||||||
require.Equal(t, expected, rr.Report(ts))
|
require.Equal(t, expected, rr.Report(ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRtcpReceiverOverflow(t *testing.T) {
|
func TestRTCPReceiverOverflow(t *testing.T) {
|
||||||
v := uint32(0x65f83afb)
|
v := uint32(0x65f83afb)
|
||||||
rr := New(&v, 90000)
|
rr := New(&v, 90000)
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ func TestRtcpReceiverOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := srPkt.Marshal()
|
byts, _ := srPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtcp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTCP, byts)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -100,7 +100,7 @@ func TestRtcpReceiverOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -115,7 +115,7 @@ func TestRtcpReceiverOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.ReceiverReport{
|
expectedPkt := rtcp.ReceiverReport{
|
||||||
SSRC: 0x65f83afb,
|
SSRC: 0x65f83afb,
|
||||||
@@ -133,7 +133,7 @@ func TestRtcpReceiverOverflow(t *testing.T) {
|
|||||||
require.Equal(t, expected, rr.Report(ts))
|
require.Equal(t, expected, rr.Report(ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRtcpReceiverPacketLost(t *testing.T) {
|
func TestRTCPReceiverPacketLost(t *testing.T) {
|
||||||
v := uint32(0x65f83afb)
|
v := uint32(0x65f83afb)
|
||||||
rr := New(&v, 90000)
|
rr := New(&v, 90000)
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ func TestRtcpReceiverPacketLost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := srPkt.Marshal()
|
byts, _ := srPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtcp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTCP, byts)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -161,7 +161,7 @@ func TestRtcpReceiverPacketLost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -176,7 +176,7 @@ func TestRtcpReceiverPacketLost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.ReceiverReport{
|
expectedPkt := rtcp.ReceiverReport{
|
||||||
SSRC: 0x65f83afb,
|
SSRC: 0x65f83afb,
|
||||||
@@ -199,7 +199,7 @@ func TestRtcpReceiverPacketLost(t *testing.T) {
|
|||||||
require.Equal(t, expected, rr.Report(ts))
|
require.Equal(t, expected, rr.Report(ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRtcpReceiverOverflowPacketLost(t *testing.T) {
|
func TestRTCPReceiverOverflowPacketLost(t *testing.T) {
|
||||||
v := uint32(0x65f83afb)
|
v := uint32(0x65f83afb)
|
||||||
rr := New(&v, 90000)
|
rr := New(&v, 90000)
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ func TestRtcpReceiverOverflowPacketLost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := srPkt.Marshal()
|
byts, _ := srPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtcp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTCP, byts)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -227,7 +227,7 @@ func TestRtcpReceiverOverflowPacketLost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -242,7 +242,7 @@ func TestRtcpReceiverOverflowPacketLost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.ReceiverReport{
|
expectedPkt := rtcp.ReceiverReport{
|
||||||
SSRC: 0x65f83afb,
|
SSRC: 0x65f83afb,
|
||||||
@@ -265,7 +265,7 @@ func TestRtcpReceiverOverflowPacketLost(t *testing.T) {
|
|||||||
require.Equal(t, expected, rr.Report(ts))
|
require.Equal(t, expected, rr.Report(ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRtcpReceiverReorderedPackets(t *testing.T) {
|
func TestRTCPReceiverReorderedPackets(t *testing.T) {
|
||||||
v := uint32(0x65f83afb)
|
v := uint32(0x65f83afb)
|
||||||
rr := New(&v, 90000)
|
rr := New(&v, 90000)
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ func TestRtcpReceiverReorderedPackets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := srPkt.Marshal()
|
byts, _ := srPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtcp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTCP, byts)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -293,7 +293,7 @@ func TestRtcpReceiverReorderedPackets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -308,7 +308,7 @@ func TestRtcpReceiverReorderedPackets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.ReceiverReport{
|
expectedPkt := rtcp.ReceiverReport{
|
||||||
SSRC: 0x65f83afb,
|
SSRC: 0x65f83afb,
|
||||||
@@ -326,7 +326,7 @@ func TestRtcpReceiverReorderedPackets(t *testing.T) {
|
|||||||
require.Equal(t, expected, rr.Report(ts))
|
require.Equal(t, expected, rr.Report(ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRtcpReceiverJitter(t *testing.T) {
|
func TestRTCPReceiverJitter(t *testing.T) {
|
||||||
v := uint32(0x65f83afb)
|
v := uint32(0x65f83afb)
|
||||||
rr := New(&v, 90000)
|
rr := New(&v, 90000)
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ func TestRtcpReceiverJitter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := srPkt.Marshal()
|
byts, _ := srPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtcp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTCP, byts)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -354,7 +354,7 @@ func TestRtcpReceiverJitter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -369,7 +369,7 @@ func TestRtcpReceiverJitter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 21, 0, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 21, 0, time.UTC)
|
||||||
rr.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rr.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.ReceiverReport{
|
expectedPkt := rtcp.ReceiverReport{
|
||||||
SSRC: 0x65f83afb,
|
SSRC: 0x65f83afb,
|
||||||
|
@@ -11,44 +11,44 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RtcpSender is a utility to generate RTCP sender reports.
|
// RTCPSender is a utility to generate RTCP sender reports.
|
||||||
type RtcpSender struct {
|
type RTCPSender struct {
|
||||||
clockRate float64
|
clockRate float64
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
|
|
||||||
// data from rtp packets
|
// data from rtp packets
|
||||||
firstRtpReceived bool
|
firstRTPReceived bool
|
||||||
senderSSRC uint32
|
senderSSRC uint32
|
||||||
lastRtpTimeRtp uint32
|
lastRTPTimeRTP uint32
|
||||||
lastRtpTimeTime time.Time
|
lastRTPTimeTime time.Time
|
||||||
packetCount uint32
|
packetCount uint32
|
||||||
octetCount uint32
|
octetCount uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a RtcpSender.
|
// New allocates a RTCPSender.
|
||||||
func New(clockRate int) *RtcpSender {
|
func New(clockRate int) *RTCPSender {
|
||||||
return &RtcpSender{
|
return &RTCPSender{
|
||||||
clockRate: float64(clockRate),
|
clockRate: float64(clockRate),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessFrame extracts the needed data from RTP or RTCP frames.
|
// ProcessFrame extracts the needed data from RTP or RTCP frames.
|
||||||
func (rs *RtcpSender) ProcessFrame(ts time.Time, streamType base.StreamType, buf []byte) {
|
func (rs *RTCPSender) ProcessFrame(ts time.Time, streamType base.StreamType, buf []byte) {
|
||||||
rs.mutex.Lock()
|
rs.mutex.Lock()
|
||||||
defer rs.mutex.Unlock()
|
defer rs.mutex.Unlock()
|
||||||
|
|
||||||
if streamType == base.StreamTypeRtp {
|
if streamType == base.StreamTypeRTP {
|
||||||
pkt := rtp.Packet{}
|
pkt := rtp.Packet{}
|
||||||
err := pkt.Unmarshal(buf)
|
err := pkt.Unmarshal(buf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if !rs.firstRtpReceived {
|
if !rs.firstRTPReceived {
|
||||||
rs.firstRtpReceived = true
|
rs.firstRTPReceived = true
|
||||||
rs.senderSSRC = pkt.SSRC
|
rs.senderSSRC = pkt.SSRC
|
||||||
}
|
}
|
||||||
|
|
||||||
// always update time to minimize errors
|
// always update time to minimize errors
|
||||||
rs.lastRtpTimeRtp = pkt.Timestamp
|
rs.lastRTPTimeRTP = pkt.Timestamp
|
||||||
rs.lastRtpTimeTime = ts
|
rs.lastRTPTimeTime = ts
|
||||||
|
|
||||||
rs.packetCount++
|
rs.packetCount++
|
||||||
rs.octetCount += uint32(len(pkt.Payload))
|
rs.octetCount += uint32(len(pkt.Payload))
|
||||||
@@ -58,11 +58,11 @@ func (rs *RtcpSender) ProcessFrame(ts time.Time, streamType base.StreamType, buf
|
|||||||
|
|
||||||
// Report generates a RTCP sender report.
|
// Report generates a RTCP sender report.
|
||||||
// It returns nil if no packets has been passed to ProcessFrame yet.
|
// It returns nil if no packets has been passed to ProcessFrame yet.
|
||||||
func (rs *RtcpSender) Report(ts time.Time) []byte {
|
func (rs *RTCPSender) Report(ts time.Time) []byte {
|
||||||
rs.mutex.Lock()
|
rs.mutex.Lock()
|
||||||
defer rs.mutex.Unlock()
|
defer rs.mutex.Unlock()
|
||||||
|
|
||||||
if !rs.firstRtpReceived {
|
if !rs.firstRTPReceived {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ func (rs *RtcpSender) Report(ts time.Time) []byte {
|
|||||||
fractionalPart := uint32((s - float64(integerPart)) * 0xFFFFFFFF)
|
fractionalPart := uint32((s - float64(integerPart)) * 0xFFFFFFFF)
|
||||||
return uint64(integerPart)<<32 | uint64(fractionalPart)
|
return uint64(integerPart)<<32 | uint64(fractionalPart)
|
||||||
}(),
|
}(),
|
||||||
RTPTime: rs.lastRtpTimeRtp + uint32((ts.Sub(rs.lastRtpTimeTime)).Seconds()*rs.clockRate),
|
RTPTime: rs.lastRTPTimeRTP + uint32((ts.Sub(rs.lastRTPTimeTime)).Seconds()*rs.clockRate),
|
||||||
PacketCount: rs.packetCount,
|
PacketCount: rs.packetCount,
|
||||||
OctetCount: rs.octetCount,
|
OctetCount: rs.octetCount,
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRtcpSender(t *testing.T) {
|
func TestRTCPSender(t *testing.T) {
|
||||||
rs := New(90000)
|
rs := New(90000)
|
||||||
|
|
||||||
rtpPkt := rtp.Packet{
|
rtpPkt := rtp.Packet{
|
||||||
@@ -27,7 +27,7 @@ func TestRtcpSender(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ := rtpPkt.Marshal()
|
byts, _ := rtpPkt.Marshal()
|
||||||
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
ts := time.Date(2008, 05, 20, 22, 15, 20, 0, time.UTC)
|
||||||
rs.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rs.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
rtpPkt = rtp.Packet{
|
rtpPkt = rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
@@ -42,7 +42,7 @@ func TestRtcpSender(t *testing.T) {
|
|||||||
}
|
}
|
||||||
byts, _ = rtpPkt.Marshal()
|
byts, _ = rtpPkt.Marshal()
|
||||||
ts = time.Date(2008, 05, 20, 22, 15, 20, 500000000, time.UTC)
|
ts = time.Date(2008, 05, 20, 22, 15, 20, 500000000, time.UTC)
|
||||||
rs.ProcessFrame(ts, base.StreamTypeRtp, byts)
|
rs.ProcessFrame(ts, base.StreamTypeRTP, byts)
|
||||||
|
|
||||||
expectedPkt := rtcp.SenderReport{
|
expectedPkt := rtcp.SenderReport{
|
||||||
SSRC: 0xba9da416,
|
SSRC: 0xba9da416,
|
||||||
|
@@ -588,7 +588,7 @@ func (sc *ServerConn) WriteFrame(trackID int, streamType StreamType, payload []b
|
|||||||
track := sc.tracks[trackID]
|
track := sc.tracks[trackID]
|
||||||
|
|
||||||
if track.proto == StreamProtocolUDP {
|
if track.proto == StreamProtocolUDP {
|
||||||
if streamType == StreamTypeRtp {
|
if streamType == StreamTypeRTP {
|
||||||
return sc.s.conf.UDPRTPListener.write(sc.s.conf.WriteTimeout, payload, &net.UDPAddr{
|
return sc.s.conf.UDPRTPListener.write(sc.s.conf.WriteTimeout, payload, &net.UDPAddr{
|
||||||
IP: sc.ip(),
|
IP: sc.ip(),
|
||||||
Zone: sc.zone(),
|
Zone: sc.zone(),
|
||||||
|
Reference in New Issue
Block a user