client: decode and encode RTP/RTCP packets

This commit is contained in:
aler9
2021-12-04 21:23:34 +01:00
committed by Alessandro Ros
parent 9a0eed07b3
commit b7df36d4ad
26 changed files with 422 additions and 332 deletions

View File

@@ -21,6 +21,9 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"github.com/aler9/gortsplib/pkg/auth" "github.com/aler9/gortsplib/pkg/auth"
"github.com/aler9/gortsplib/pkg/base" "github.com/aler9/gortsplib/pkg/base"
"github.com/aler9/gortsplib/pkg/headers" "github.com/aler9/gortsplib/pkg/headers"
@@ -132,9 +135,9 @@ type Client struct {
// called after every response. // called after every response.
OnResponse func(*base.Response) OnResponse func(*base.Response)
// called when a RTP packet arrives. // called when a RTP packet arrives.
OnPacketRTP func(int, []byte) OnPacketRTP func(int, *rtp.Packet)
// called when a RTCP packet arrives. // called when a RTCP packet arrives.
OnPacketRTCP func(int, []byte) OnPacketRTCP func(int, rtcp.Packet)
// //
// RTSP parameters // RTSP parameters
@@ -249,11 +252,11 @@ type Client struct {
func (c *Client) Start(scheme string, host string) error { func (c *Client) Start(scheme string, host string) error {
// callbacks // callbacks
if c.OnPacketRTP == nil { if c.OnPacketRTP == nil {
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
} }
} }
if c.OnPacketRTCP == nil { if c.OnPacketRTCP == nil {
c.OnPacketRTCP = func(trackID int, payload []byte) { c.OnPacketRTCP = func(trackID int, pkt rtcp.Packet) {
} }
} }
@@ -757,17 +760,37 @@ func (c *Client) runReader() {
atomic.StoreInt64(c.tcpLastFrameTime, now.Unix()) atomic.StoreInt64(c.tcpLastFrameTime, now.Unix())
if isRTP { if isRTP {
c.tracks[trackID].rtcpReceiver.ProcessPacketRTP(now, payload) var pkt rtp.Packet
c.OnPacketRTP(trackID, payload) err := pkt.Unmarshal(payload)
if err != nil {
return
}
c.tracks[trackID].rtcpReceiver.ProcessPacketRTP(now, &pkt)
c.OnPacketRTP(trackID, &pkt)
} else { } else {
c.tracks[trackID].rtcpReceiver.ProcessPacketRTCP(now, payload) packets, err := rtcp.Unmarshal(payload)
c.OnPacketRTCP(trackID, payload) if err != nil {
return
}
for _, pkt := range packets {
c.tracks[trackID].rtcpReceiver.ProcessPacketRTCP(now, pkt)
c.OnPacketRTCP(trackID, pkt)
}
} }
} }
} else { } else {
processFunc = func(trackID int, isRTP bool, payload []byte) { processFunc = func(trackID int, isRTP bool, payload []byte) {
if !isRTP { if !isRTP {
c.OnPacketRTCP(trackID, payload) packets, err := rtcp.Unmarshal(payload)
if err != nil {
return
}
for _, pkt := range packets {
c.OnPacketRTCP(trackID, pkt)
}
} }
} }
} }
@@ -1585,11 +1608,13 @@ func (c *Client) doPlay(ra *headers.Range, isSwitchingProtocol bool) (*base.Resp
// open the firewall by sending packets to the counterpart. // open the firewall by sending packets to the counterpart.
for _, cct := range c.tracks { for _, cct := range c.tracks {
cct.udpRTPListener.write( byts, _ := (&rtp.Packet{
[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) Header: rtp.Header{Version: 2},
}).Marshal()
cct.udpRTPListener.write(byts)
cct.udpRTCPListener.write( byts, _ = (&rtcp.ReceiverReport{}).Marshal()
[]byte{0x80, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}) cct.udpRTCPListener.write(byts)
} }
} }
@@ -1806,10 +1831,6 @@ func (c *Client) runWriter() {
case TransportUDP, TransportUDPMulticast: case TransportUDP, TransportUDPMulticast:
writeFunc = func(trackID int, isRTP bool, payload []byte) { writeFunc = func(trackID int, isRTP bool, payload []byte) {
if isRTP { if isRTP {
if c.tracks[trackID].rtcpSender != nil {
c.tracks[trackID].rtcpSender.ProcessPacketRTP(time.Now(), payload)
}
c.tracks[trackID].udpRTPListener.write(payload) c.tracks[trackID].udpRTPListener.write(payload)
} else { } else {
c.tracks[trackID].udpRTCPListener.write(payload) c.tracks[trackID].udpRTCPListener.write(payload)
@@ -1821,10 +1842,6 @@ func (c *Client) runWriter() {
writeFunc = func(trackID int, isRTP bool, payload []byte) { writeFunc = func(trackID int, isRTP bool, payload []byte) {
if isRTP { if isRTP {
if c.tracks[trackID].rtcpSender != nil {
c.tracks[trackID].rtcpSender.ProcessPacketRTP(time.Now(), payload)
}
f := c.tracks[trackID].tcpRTPFrame f := c.tracks[trackID].tcpRTPFrame
f.Payload = payload f.Payload = payload
f.Write(&buf) f.Write(&buf)
@@ -1854,7 +1871,7 @@ func (c *Client) runWriter() {
} }
// WritePacketRTP writes a RTP packet. // WritePacketRTP writes a RTP packet.
func (c *Client) WritePacketRTP(trackID int, payload []byte) error { func (c *Client) WritePacketRTP(trackID int, pkt *rtp.Packet) error {
c.writeMutex.RLock() c.writeMutex.RLock()
defer c.writeMutex.RUnlock() defer c.writeMutex.RUnlock()
@@ -1867,16 +1884,25 @@ func (c *Client) WritePacketRTP(trackID int, payload []byte) error {
} }
} }
byts, err := pkt.Marshal()
if err != nil {
return err
}
if c.tracks[trackID].rtcpSender != nil {
c.tracks[trackID].rtcpSender.ProcessPacketRTP(time.Now(), pkt)
}
c.writeBuffer.Push(trackTypePayload{ c.writeBuffer.Push(trackTypePayload{
trackID: trackID, trackID: trackID,
isRTP: true, isRTP: true,
payload: payload, payload: byts,
}) })
return nil return nil
} }
// WritePacketRTCP writes a RTCP packet. // WritePacketRTCP writes a RTCP packet.
func (c *Client) WritePacketRTCP(trackID int, payload []byte) error { func (c *Client) WritePacketRTCP(trackID int, pkt rtcp.Packet) error {
c.writeMutex.RLock() c.writeMutex.RLock()
defer c.writeMutex.RUnlock() defer c.writeMutex.RUnlock()
@@ -1889,10 +1915,15 @@ func (c *Client) WritePacketRTCP(trackID int, payload []byte) error {
} }
} }
byts, err := pkt.Marshal()
if err != nil {
return err
}
c.writeBuffer.Push(trackTypePayload{ c.writeBuffer.Push(trackTypePayload{
trackID: trackID, trackID: trackID,
isRTP: false, isRTP: false,
payload: payload, payload: byts,
}) })
return nil return nil
} }

View File

@@ -18,6 +18,39 @@ import (
"github.com/aler9/gortsplib/pkg/rtcpreceiver" "github.com/aler9/gortsplib/pkg/rtcpreceiver"
) )
var testRTPPacket = rtp.Packet{
Header: rtp.Header{
Version: 2,
PayloadType: 97,
CSRC: []uint32{},
},
Payload: []byte{0x01, 0x02, 0x03, 0x04},
}
var testRTPPacketMarshaled = func() []byte {
byts, _ := testRTPPacket.Marshal()
return byts
}()
var testRTCPPacket = rtcp.SourceDescription{
Chunks: []rtcp.SourceDescriptionChunk{
{
Source: 1234,
Items: []rtcp.SourceDescriptionItem{
{
Type: rtcp.SDESCNAME,
Text: "myname",
},
},
},
},
}
var testRTCPPacketMarshaled = func() []byte {
byts, _ := testRTCPPacket.Marshal()
return byts
}()
func TestClientPublishSerial(t *testing.T) { func TestClientPublishSerial(t *testing.T) {
for _, transport := range []string{ for _, transport := range []string{
"udp", "udp",
@@ -138,31 +171,37 @@ func TestClientPublishSerial(t *testing.T) {
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
// client -> server // client -> server (RTP)
if transport == "udp" { if transport == "udp" {
buf := make([]byte, 2048) buf := make([]byte, 2048)
n, _, err := l1.ReadFrom(buf) n, _, err := l1.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, buf[:n]) var pkt rtp.Packet
err = pkt.Unmarshal(buf[:n])
require.NoError(t, err)
require.Equal(t, testRTPPacket, pkt)
} else { } else {
var f base.InterleavedFrame var f base.InterleavedFrame
f.Payload = make([]byte, 2048) f.Payload = make([]byte, 2048)
err = f.Read(br) err = f.Read(br)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, f.Channel) require.Equal(t, 0, f.Channel)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, f.Payload) var pkt rtp.Packet
err = pkt.Unmarshal(f.Payload)
require.NoError(t, err)
require.Equal(t, testRTPPacket, pkt)
} }
// server -> client (RTCP) // server -> client (RTCP)
if transport == "udp" { if transport == "udp" {
l2.WriteTo([]byte{0x05, 0x06, 0x07, 0x08}, &net.UDPAddr{ l2.WriteTo(testRTCPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: th.ClientPorts[1], Port: th.ClientPorts[1],
}) })
} else { } else {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 1, Channel: 1,
Payload: []byte{0x05, 0x06, 0x07, 0x08}, Payload: testRTCPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -194,9 +233,9 @@ func TestClientPublishSerial(t *testing.T) {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTCP: func(trackID int, payload []byte) { OnPacketRTCP: func(trackID int, pkt rtcp.Packet) {
require.Equal(t, 0, trackID) require.Equal(t, 0, trackID)
require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, payload) require.Equal(t, &testRTCPPacket, pkt)
close(recvDone) close(recvDone)
}, },
} }
@@ -214,16 +253,14 @@ func TestClientPublishSerial(t *testing.T) {
c.Wait() c.Wait()
}() }()
err = c.WritePacketRTP(0, err = c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
require.NoError(t, err) require.NoError(t, err)
<-recvDone <-recvDone
c.Close() c.Close()
<-done <-done
err = c.WritePacketRTP(0, err = c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
require.Error(t, err) require.Error(t, err)
}) })
} }
@@ -376,8 +413,7 @@ func TestClientPublishParallel(t *testing.T) {
defer t.Stop() defer t.Stop()
for range t.C { for range t.C {
err := c.WritePacketRTP(0, err := c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
if err != nil { if err != nil {
return return
} }
@@ -531,8 +567,7 @@ func TestClientPublishPauseSerial(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer c.Close() defer c.Close()
err = c.WritePacketRTP(0, err = c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
require.NoError(t, err) require.NoError(t, err)
_, err = c.Pause() _, err = c.Pause()
@@ -541,8 +576,7 @@ func TestClientPublishPauseSerial(t *testing.T) {
_, err = c.Record() _, err = c.Record()
require.NoError(t, err) require.NoError(t, err)
err = c.WritePacketRTP(0, err = c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
require.NoError(t, err) require.NoError(t, err)
}) })
} }
@@ -677,8 +711,7 @@ func TestClientPublishPauseParallel(t *testing.T) {
defer t.Stop() defer t.Stop()
for range t.C { for range t.C {
err := c.WritePacketRTP(0, err := c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
if err != nil { if err != nil {
return return
} }
@@ -794,7 +827,10 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
err = f.Read(br) err = f.Read(br)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, f.Channel) require.Equal(t, 0, f.Channel)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, f.Payload) var pkt rtp.Packet
err = pkt.Unmarshal(f.Payload)
require.NoError(t, err)
require.Equal(t, testRTPPacket, pkt)
req, err = readRequest(br) req, err = readRequest(br)
require.NoError(t, err) require.NoError(t, err)
@@ -817,8 +853,7 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer c.Close() defer c.Close()
err = c.WritePacketRTP(0, err = c.WritePacketRTP(0, &testRTPPacket)
[]byte{0x01, 0x02, 0x03, 0x04})
require.NoError(t, err) require.NoError(t, err)
} }
@@ -915,14 +950,17 @@ func TestClientPublishRTCPReport(t *testing.T) {
buf := make([]byte, 2048) buf := make([]byte, 2048)
n, _, err := l1.ReadFrom(buf) n, _, err := l1.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
rr.ProcessPacketRTP(time.Now(), buf[:n]) var pkt rtp.Packet
err = pkt.Unmarshal(buf[:n])
require.NoError(t, err)
rr.ProcessPacketRTP(time.Now(), &pkt)
buf = make([]byte, 2048) buf = make([]byte, 2048)
n, _, err = l2.ReadFrom(buf) n, _, err = l2.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
pkt, err := rtcp.Unmarshal(buf[:n]) packets, err := rtcp.Unmarshal(buf[:n])
require.NoError(t, err) require.NoError(t, err)
sr, ok := pkt[0].(*rtcp.SenderReport) sr, ok := packets[0].(*rtcp.SenderReport)
require.True(t, ok) require.True(t, ok)
require.Equal(t, &rtcp.SenderReport{ require.Equal(t, &rtcp.SenderReport{
SSRC: 753621, SSRC: 753621,
@@ -931,7 +969,7 @@ func TestClientPublishRTCPReport(t *testing.T) {
PacketCount: 1, PacketCount: 1,
OctetCount: 4, OctetCount: 4,
}, sr) }, sr)
rr.ProcessPacketRTCP(time.Now(), buf[:n]) rr.ProcessPacketRTCP(time.Now(), packets[0])
close(reportReceived) close(reportReceived)
@@ -958,7 +996,7 @@ func TestClientPublishRTCPReport(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer c.Close() defer c.Close()
byts, _ := (&rtp.Packet{ err = c.WritePacketRTP(0, &rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
Version: 2, Version: 2,
Marker: true, Marker: true,
@@ -968,8 +1006,7 @@ func TestClientPublishRTCPReport(t *testing.T) {
SSRC: 753621, SSRC: 753621,
}, },
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: []byte{0x01, 0x02, 0x03, 0x04},
}).Marshal() })
err = c.WritePacketRTP(0, byts)
require.NoError(t, err) require.NoError(t, err)
<-reportReceived <-reportReceived
@@ -1056,14 +1093,14 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 1, Channel: 1,
Payload: []byte{0x05, 0x06, 0x07, 0x08}, Payload: testRTCPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -1086,10 +1123,10 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
t.Errorf("should not happen") t.Errorf("should not happen")
}, },
OnPacketRTCP: func(trackID int, payload []byte) { OnPacketRTCP: func(trackID int, pkt rtcp.Packet) {
close(rtcpReceived) close(rtcpReceived)
}, },
} }

View File

@@ -317,18 +317,18 @@ func TestClientRead(t *testing.T) {
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
// server -> client // server -> client (RTP)
switch transport { switch transport {
case "udp": case "udp":
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
l1.WriteTo([]byte{0x01, 0x02, 0x03, 0x04}, &net.UDPAddr{ l1.WriteTo(testRTPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: th.ClientPorts[0], Port: th.ClientPorts[0],
}) })
case "multicast": case "multicast":
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
l1.WriteTo([]byte{0x01, 0x02, 0x03, 0x04}, &net.UDPAddr{ l1.WriteTo(testRTPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("224.1.0.1"), IP: net.ParseIP("224.1.0.1"),
Port: 25000, Port: 25000,
}) })
@@ -336,7 +336,7 @@ func TestClientRead(t *testing.T) {
case "tcp", "tls": case "tcp", "tls":
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -353,7 +353,9 @@ func TestClientRead(t *testing.T) {
buf = make([]byte, 2048) buf = make([]byte, 2048)
n, _, err := l2.ReadFrom(buf) n, _, err := l2.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, buf[:n]) packets, err := rtcp.Unmarshal(buf[:n])
require.NoError(t, err)
require.Equal(t, &testRTCPPacket, packets[0])
close(packetRecv) close(packetRecv)
case "tcp", "tls": case "tcp", "tls":
@@ -362,7 +364,9 @@ func TestClientRead(t *testing.T) {
err := f.Read(br) err := f.Read(br)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, f.Channel) require.Equal(t, 1, f.Channel)
require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, f.Payload) packets, err := rtcp.Unmarshal(f.Payload)
require.NoError(t, err)
require.Equal(t, &testRTCPPacket, packets[0])
close(packetRecv) close(packetRecv)
} }
@@ -401,7 +405,7 @@ func TestClientRead(t *testing.T) {
}(), }(),
} }
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
// ignore multicast loopback // ignore multicast loopback
if transport == "multicast" { if transport == "multicast" {
counter++ counter++
@@ -411,9 +415,9 @@ func TestClientRead(t *testing.T) {
} }
require.Equal(t, 0, trackID) require.Equal(t, 0, trackID)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, payload) require.Equal(t, &testRTPPacket, pkt)
err := c.WritePacketRTCP(0, []byte{0x05, 0x06, 0x07, 0x08}) err := c.WritePacketRTCP(0, &testRTCPPacket)
require.NoError(t, err) require.NoError(t, err)
} }
@@ -427,7 +431,14 @@ func TestClientRead(t *testing.T) {
} }
func TestClientReadNonStandardFrameSize(t *testing.T) { func TestClientReadNonStandardFrameSize(t *testing.T) {
refPayload := bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04, 0x05}, 4096/5) refRTPPacket := rtp.Packet{
Header: rtp.Header{
Version: 2,
PayloadType: 96,
CSRC: []uint32{},
},
Payload: bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04, 0x05}, 4096/5),
}
l, err := net.Listen("tcp", "localhost:8554") l, err := net.Listen("tcp", "localhost:8554")
require.NoError(t, err) require.NoError(t, err)
@@ -519,9 +530,10 @@ func TestClientReadNonStandardFrameSize(t *testing.T) {
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
byts, _ := refRTPPacket.Marshal()
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: refPayload, Payload: byts,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -530,14 +542,14 @@ func TestClientReadNonStandardFrameSize(t *testing.T) {
packetRecv := make(chan struct{}) packetRecv := make(chan struct{})
c := &Client{ c := &Client{
ReadBufferSize: 4500, ReadBufferSize: 4500 + 4,
Transport: func() *Transport { Transport: func() *Transport {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
require.Equal(t, 0, trackID) require.Equal(t, 0, trackID)
require.Equal(t, refPayload, payload) require.Equal(t, &refRTPPacket, pkt)
close(packetRecv) close(packetRecv)
}, },
} }
@@ -632,7 +644,7 @@ func TestClientReadPartial(t *testing.T) {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -656,9 +668,9 @@ func TestClientReadPartial(t *testing.T) {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
require.Equal(t, 0, trackID) require.Equal(t, 0, trackID)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, payload) require.Equal(t, &testRTPPacket, pkt)
close(packetRecv) close(packetRecv)
}, },
} }
@@ -916,11 +928,12 @@ func TestClientReadAnyPort(t *testing.T) {
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
l1a.WriteTo([]byte{0x01, 0x02, 0x03, 0x04}, &net.UDPAddr{ l1a.WriteTo(testRTPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: th.ClientPorts[0], Port: th.ClientPorts[0],
}) })
// read RTCP
if ca == "random" { if ca == "random" {
// skip firewall opening // skip firewall opening
buf := make([]byte, 2048) buf := make([]byte, 2048)
@@ -930,7 +943,9 @@ func TestClientReadAnyPort(t *testing.T) {
buf = make([]byte, 2048) buf = make([]byte, 2048)
n, _, err := l1b.ReadFrom(buf) n, _, err := l1b.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, buf[:n], []byte{0x05, 0x06, 0x07, 0x08}) packets, err := rtcp.Unmarshal(buf[:n])
require.NoError(t, err)
require.Equal(t, &testRTCPPacket, packets[0])
close(serverRecv) close(serverRecv)
} }
}() }()
@@ -939,8 +954,8 @@ func TestClientReadAnyPort(t *testing.T) {
c := &Client{ c := &Client{
AnyPortEnable: true, AnyPortEnable: true,
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
require.Equal(t, payload, []byte{0x01, 0x02, 0x03, 0x04}) require.Equal(t, &testRTPPacket, pkt)
close(packetRecv) close(packetRecv)
}, },
} }
@@ -952,7 +967,7 @@ func TestClientReadAnyPort(t *testing.T) {
<-packetRecv <-packetRecv
if ca == "random" { if ca == "random" {
c.WritePacketRTCP(0, []byte{0x05, 0x06, 0x07, 0x08}) c.WritePacketRTCP(0, &testRTCPPacket)
<-serverRecv <-serverRecv
} }
}) })
@@ -1061,7 +1076,7 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte("\x00\x00\x00\x00"), Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -1070,7 +1085,7 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
packetRecv := make(chan struct{}) packetRecv := make(chan struct{})
c := Client{ c := Client{
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
close(packetRecv) close(packetRecv)
}, },
} }
@@ -1279,7 +1294,7 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte("\x00\x00\x00\x00"), Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -1301,7 +1316,7 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
c := &Client{ c := &Client{
ReadTimeout: 1 * time.Second, ReadTimeout: 1 * time.Second,
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
close(packetRecv) close(packetRecv)
}, },
} }
@@ -1409,7 +1424,7 @@ func TestClientReadDifferentInterleavedIDs(t *testing.T) {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 2, Channel: 2,
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -1433,7 +1448,7 @@ func TestClientReadDifferentInterleavedIDs(t *testing.T) {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
require.Equal(t, 0, trackID) require.Equal(t, 0, trackID)
close(packetRecv) close(packetRecv)
}, },
@@ -1577,7 +1592,7 @@ func TestClientReadRedirect(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer l1.Close() defer l1.Close()
l1.WriteTo([]byte("\x00\x00\x00\x00"), &net.UDPAddr{ l1.WriteTo(testRTPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: th.ClientPorts[0], Port: th.ClientPorts[0],
}) })
@@ -1586,7 +1601,7 @@ func TestClientReadRedirect(t *testing.T) {
packetRecv := make(chan struct{}) packetRecv := make(chan struct{})
c := Client{ c := Client{
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
close(packetRecv) close(packetRecv)
}, },
} }
@@ -1622,14 +1637,14 @@ func TestClientReadPause(t *testing.T) {
select { select {
case <-t.C: case <-t.C:
if inTH.Protocol == headers.TransportProtocolUDP { if inTH.Protocol == headers.TransportProtocolUDP {
l1.WriteTo([]byte("\x00\x00\x00\x00"), &net.UDPAddr{ l1.WriteTo(testRTPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: inTH.ClientPorts[0], Port: inTH.ClientPorts[0],
}) })
} else { } else {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte("\x00\x00\x00\x00"), Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
conn.Write(bb.Bytes()) conn.Write(bb.Bytes())
} }
@@ -1797,7 +1812,7 @@ func TestClientReadPause(t *testing.T) {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
if atomic.SwapInt32(&firstFrame, 1) == 0 { if atomic.SwapInt32(&firstFrame, 1) == 0 {
close(packetRecv) close(packetRecv)
} }
@@ -1930,7 +1945,7 @@ func TestClientReadRTCPReport(t *testing.T) {
rs := rtcpsender.New(90000) rs := rtcpsender.New(90000)
byts, _ := (&rtp.Packet{ pkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
Version: 2, Version: 2,
Marker: true, Marker: true,
@@ -1940,15 +1955,18 @@ func TestClientReadRTCPReport(t *testing.T) {
SSRC: 753621, SSRC: 753621,
}, },
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: []byte{0x01, 0x02, 0x03, 0x04},
}).Marshal() }
byts, _ := pkt.Marshal()
_, err = l1.WriteTo(byts, &net.UDPAddr{ _, err = l1.WriteTo(byts, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: inTH.ClientPorts[0], Port: inTH.ClientPorts[0],
}) })
require.NoError(t, err) require.NoError(t, err)
rs.ProcessPacketRTP(time.Now(), byts) rs.ProcessPacketRTP(time.Now(), &pkt)
_, err = l2.WriteTo(rs.Report(time.Now()), &net.UDPAddr{ sr := rs.Report(time.Now())
byts, _ = sr.Marshal()
_, err = l2.WriteTo(byts, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: inTH.ClientPorts[1], Port: inTH.ClientPorts[1],
}) })
@@ -1957,9 +1975,9 @@ func TestClientReadRTCPReport(t *testing.T) {
buf = make([]byte, 2048) buf = make([]byte, 2048)
n, _, err := l2.ReadFrom(buf) n, _, err := l2.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
pkt, err := rtcp.Unmarshal(buf[:n]) packets, err := rtcp.Unmarshal(buf[:n])
require.NoError(t, err) require.NoError(t, err)
rr, ok := pkt[0].(*rtcp.ReceiverReport) rr, ok := packets[0].(*rtcp.ReceiverReport)
require.True(t, ok) require.True(t, ok)
require.Equal(t, &rtcp.ReceiverReport{ require.Equal(t, &rtcp.ReceiverReport{
SSRC: rr.SSRC, SSRC: rr.SSRC,
@@ -2109,7 +2127,7 @@ func TestClientReadErrorTimeout(t *testing.T) {
if transport == "udp" || transport == "auto" { if transport == "udp" || transport == "auto" {
// write a packet to skip the protocol autodetection feature // write a packet to skip the protocol autodetection feature
l1.WriteTo([]byte("\x01\x02\x03\x04"), &net.UDPAddr{ l1.WriteTo(testRTPPacketMarshaled, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"), IP: net.ParseIP("127.0.0.1"),
Port: th.ClientPorts[0], Port: th.ClientPorts[0],
}) })
@@ -2251,14 +2269,14 @@ func TestClientReadIgnoreTCPInvalidTrack(t *testing.T) {
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 6, Channel: 6,
Payload: []byte{0x01, 0x02, 0x03, 0x04}, Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
base.InterleavedFrame{ base.InterleavedFrame{
Channel: 0, Channel: 0,
Payload: []byte{0x05, 0x06, 0x07, 0x08}, Payload: testRTPPacketMarshaled,
}.Write(&bb) }.Write(&bb)
_, err = conn.Write(bb.Bytes()) _, err = conn.Write(bb.Bytes())
require.NoError(t, err) require.NoError(t, err)
@@ -2281,7 +2299,7 @@ func TestClientReadIgnoreTCPInvalidTrack(t *testing.T) {
v := TransportTCP v := TransportTCP
return &v return &v
}(), }(),
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
close(recv) close(recv)
}, },
} }

View File

@@ -7,6 +7,8 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"github.com/aler9/gortsplib/pkg/multibuffer" "github.com/aler9/gortsplib/pkg/multibuffer"
@@ -35,6 +37,7 @@ type clientUDPListener struct {
readBuffer *multibuffer.MultiBuffer readBuffer *multibuffer.MultiBuffer
lastPacketTime *int64 lastPacketTime *int64
processFunc func(time.Time, []byte) processFunc func(time.Time, []byte)
rtpPkt rtp.Packet
readerDone chan struct{} readerDone chan struct{}
} }
@@ -136,7 +139,7 @@ func (l *clientUDPListener) start(forPlay bool) {
l.processFunc = l.processPlayRTCP l.processFunc = l.processPlayRTCP
} }
} else { } else {
l.processFunc = l.processRecord l.processFunc = l.processRecordRTCP
} }
l.running = true l.running = true
@@ -174,24 +177,43 @@ func (l *clientUDPListener) runReader() {
} }
func (l *clientUDPListener) processPlayRTP(now time.Time, payload []byte) { func (l *clientUDPListener) processPlayRTP(now time.Time, payload []byte) {
l.c.tracks[l.trackID].rtcpReceiver.ProcessPacketRTP(now, payload) err := l.rtpPkt.Unmarshal(payload)
l.c.OnPacketRTP(l.trackID, payload) if err != nil {
return
}
l.c.tracks[l.trackID].rtcpReceiver.ProcessPacketRTP(now, &l.rtpPkt)
l.c.OnPacketRTP(l.trackID, &l.rtpPkt)
} }
func (l *clientUDPListener) processPlayRTCP(now time.Time, payload []byte) { func (l *clientUDPListener) processPlayRTCP(now time.Time, payload []byte) {
l.c.tracks[l.trackID].rtcpReceiver.ProcessPacketRTCP(now, payload) packets, err := rtcp.Unmarshal(payload)
l.c.OnPacketRTCP(l.trackID, payload) if err != nil {
return
} }
func (l *clientUDPListener) processRecord(now time.Time, payload []byte) { for _, pkt := range packets {
l.c.OnPacketRTCP(l.trackID, payload) l.c.tracks[l.trackID].rtcpReceiver.ProcessPacketRTCP(now, pkt)
l.c.OnPacketRTCP(l.trackID, pkt)
}
} }
func (l *clientUDPListener) write(buf []byte) error { func (l *clientUDPListener) processRecordRTCP(now time.Time, payload []byte) {
packets, err := rtcp.Unmarshal(payload)
if err != nil {
return
}
for _, pkt := range packets {
l.c.OnPacketRTCP(l.trackID, pkt)
}
}
func (l *clientUDPListener) write(payload []byte) error {
// no mutex is needed here since Write() has an internal lock. // no mutex is needed here since Write() has an internal lock.
// https://github.com/golang/go/issues/27203#issuecomment-534386117 // https://github.com/golang/go/issues/27203#issuecomment-534386117
l.pc.SetWriteDeadline(time.Now().Add(l.c.WriteTimeout)) l.pc.SetWriteDeadline(time.Now().Add(l.c.WriteTimeout))
_, err := l.pc.WriteTo(buf, l.remoteWriteAddr) _, err := l.pc.WriteTo(payload, l.remoteWriteAddr)
return err return err
} }

View File

@@ -5,6 +5,7 @@ import (
"net" "net"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -50,6 +51,7 @@ func main() {
defer c.Close() defer c.Close()
buf = make([]byte, 2048) buf = make([]byte, 2048)
var pkt rtp.Packet
for { for {
// read packets from the source // read packets from the source
n, _, err := pc.ReadFrom(buf) n, _, err := pc.ReadFrom(buf)
@@ -57,8 +59,14 @@ func main() {
panic(err) panic(err)
} }
// marshal RTP packets
err = pkt.Unmarshal(buf[:n])
if err != nil {
panic(err)
}
// route RTP packets to the server // route RTP packets to the server
err = c.WritePacketRTP(0, buf[:n]) err = c.WritePacketRTP(0, &pkt)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -6,6 +6,7 @@ import (
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -51,6 +52,7 @@ func main() {
defer c.Close() defer c.Close()
buf := make([]byte, 2048) buf := make([]byte, 2048)
var pkt rtp.Packet
for { for {
// read packets from the source // read packets from the source
n, _, err := pc.ReadFrom(buf) n, _, err := pc.ReadFrom(buf)
@@ -58,8 +60,14 @@ func main() {
panic(err) panic(err)
} }
// marshal RTP packets
err = pkt.Unmarshal(buf[:n])
if err != nil {
panic(err)
}
// route RTP packets to the server // route RTP packets to the server
err = c.WritePacketRTP(0, buf[:n]) err = c.WritePacketRTP(0, &pkt)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -7,6 +7,7 @@ import (
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -60,6 +61,7 @@ func main() {
defer c.Close() defer c.Close()
buf := make([]byte, 2048) buf := make([]byte, 2048)
var pkt rtp.Packet
for { for {
// read packets from the source // read packets from the source
n, _, err := pc.ReadFrom(buf) n, _, err := pc.ReadFrom(buf)
@@ -67,8 +69,14 @@ func main() {
panic(err) panic(err)
} }
// marshal RTP packets
err = pkt.Unmarshal(buf[:n])
if err != nil {
panic(err)
}
// route RTP packets to the server // route RTP packets to the server
err = c.WritePacketRTP(0, buf[:n]) err = c.WritePacketRTP(0, &pkt)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -5,6 +5,7 @@ import (
"net" "net"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -50,6 +51,7 @@ func main() {
defer c.Close() defer c.Close()
buf = make([]byte, 2048) buf = make([]byte, 2048)
var pkt rtp.Packet
for { for {
// read packets from the source // read packets from the source
n, _, err := pc.ReadFrom(buf) n, _, err := pc.ReadFrom(buf)
@@ -57,8 +59,14 @@ func main() {
panic(err) panic(err)
} }
// marshal RTP packets
err = pkt.Unmarshal(buf[:n])
if err != nil {
panic(err)
}
// route RTP packets to the server // route RTP packets to the server
err = c.WritePacketRTP(0, buf[:n]) err = c.WritePacketRTP(0, &pkt)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -7,6 +7,7 @@ import (
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -55,6 +56,7 @@ func main() {
for { for {
go func() { go func() {
buf := make([]byte, 2048) buf := make([]byte, 2048)
var pkt rtp.Packet
for { for {
// read packets from the source // read packets from the source
n, _, err := pc.ReadFrom(buf) n, _, err := pc.ReadFrom(buf)
@@ -62,8 +64,14 @@ func main() {
break break
} }
// marshal RTP packets
err = pkt.Unmarshal(buf[:n])
if err != nil {
panic(err)
}
// route RTP packets to the server // route RTP packets to the server
err = c.WritePacketRTP(0, buf[:n]) err = c.WritePacketRTP(0, &pkt)
if err != nil { if err != nil {
break break
} }

View File

@@ -61,20 +61,13 @@ func main() {
dec := rtpaac.NewDecoder(clockRate) dec := rtpaac.NewDecoder(clockRate)
// called when a RTP packet arrives // called when a RTP packet arrives
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
if trackID != aacTrack { if trackID != aacTrack {
return return
} }
// parse RTP packet
var pkt rtp.Packet
err := pkt.Unmarshal(payload)
if err != nil {
return
}
// decode AAC AUs from the RTP packet // decode AAC AUs from the RTP packet
aus, _, err := dec.Decode(&pkt) aus, _, err := dec.Decode(pkt)
if err != nil { if err != nil {
return return
} }

View File

@@ -99,20 +99,13 @@ func main() {
// called when a RTP packet arrives // called when a RTP packet arrives
saveCount := 0 saveCount := 0
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
if trackID != h264trID { if trackID != h264trID {
return return
} }
// parse RTP packet
var pkt rtp.Packet
err := pkt.Unmarshal(payload)
if err != nil {
return
}
// decode H264 NALUs from the RTP packet // decode H264 NALUs from the RTP packet
nalus, _, err := rtpDec.Decode(&pkt) nalus, _, err := rtpDec.Decode(pkt)
if err != nil { if err != nil {
return return
} }

View File

@@ -75,20 +75,13 @@ func main() {
h264dec.decode(h264tr.PPS()) h264dec.decode(h264tr.PPS())
// called when a RTP packet arrives // called when a RTP packet arrives
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
if trackID != h264trID { if trackID != h264trID {
return return
} }
// parse RTP packet
var pkt rtp.Packet
err := pkt.Unmarshal(payload)
if err != nil {
return
}
// decode H264 NALUs from the RTP packet // decode H264 NALUs from the RTP packet
nalus, _, err := rtpDec.Decode(&pkt) nalus, _, err := rtpDec.Decode(pkt)
if err != nil { if err != nil {
return return
} }

View File

@@ -67,20 +67,13 @@ func main() {
} }
// called when a RTP packet arrives // called when a RTP packet arrives
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
if trackID != h264Track { if trackID != h264Track {
return return
} }
// parse RTP packet
var pkt rtp.Packet
err := pkt.Unmarshal(payload)
if err != nil {
return
}
// decode H264 NALUs from the RTP packet // decode H264 NALUs from the RTP packet
nalus, pts, err := dec.DecodeUntilMarker(&pkt) nalus, pts, err := dec.DecodeUntilMarker(pkt)
if err != nil { if err != nil {
return return
} }

View File

@@ -5,6 +5,8 @@ import (
"time" "time"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtcp"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -21,12 +23,12 @@ func main() {
// timeout of write operations // timeout of write operations
WriteTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second,
// called when a RTP packet arrives // called when a RTP packet arrives
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
log.Printf("RTP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTP packet from track %d, payload type %d\n", trackID, pkt.Header.PayloadType)
}, },
// called when a RTCP packet arrives // called when a RTCP packet arrives
OnPacketRTCP: func(trackID int, payload []byte) { OnPacketRTCP: func(trackID int, pkt rtcp.Packet) {
log.Printf("RTCP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTCP packet from track %d, type %T\n", trackID, pkt)
}, },
} }

View File

@@ -5,6 +5,8 @@ import (
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/base" "github.com/aler9/gortsplib/pkg/base"
"github.com/pion/rtcp"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -15,12 +17,12 @@ import (
func main() { func main() {
c := gortsplib.Client{ c := gortsplib.Client{
// called when a RTP packet arrives // called when a RTP packet arrives
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
log.Printf("RTP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTP packet from track %d, payload type %d\n", trackID, pkt.Header.PayloadType)
}, },
// called when a RTCP packet arrives // called when a RTCP packet arrives
OnPacketRTCP: func(trackID int, payload []byte) { OnPacketRTCP: func(trackID int, pkt rtcp.Packet) {
log.Printf("RTCP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTCP packet from track %d, type %T\n", trackID, pkt)
}, },
} }

View File

@@ -5,6 +5,8 @@ import (
"time" "time"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtcp"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -16,12 +18,12 @@ import (
func main() { func main() {
c := gortsplib.Client{ c := gortsplib.Client{
// called when a RTP packet arrives // called when a RTP packet arrives
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
log.Printf("RTP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTP packet from track %d, payload type %d\n", trackID, pkt.Header.PayloadType)
}, },
// called when a RTCP packet arrives // called when a RTCP packet arrives
OnPacketRTCP: func(trackID int, payload []byte) { OnPacketRTCP: func(trackID int, pkt rtcp.Packet) {
log.Printf("RTCP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTCP packet from track %d, type %T\n", trackID, pkt)
}, },
} }

View File

@@ -4,6 +4,8 @@ import (
"log" "log"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtcp"
"github.com/pion/rtp"
) )
// This example shows how to // This example shows how to
@@ -12,12 +14,12 @@ import (
func main() { func main() {
c := gortsplib.Client{ c := gortsplib.Client{
// called when a RTP packet arrives // called when a RTP packet arrives
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
log.Printf("RTP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTP packet from track %d, payload type %d\n", trackID, pkt.Header.PayloadType)
}, },
// called when a RTCP packet arrives // called when a RTCP packet arrives
OnPacketRTCP: func(trackID int, payload []byte) { OnPacketRTCP: func(trackID int, pkt rtcp.Packet) {
log.Printf("RTCP packet from track %d, size %d\n", trackID, len(payload)) log.Printf("RTCP packet from track %d, type %T\n", trackID, pkt)
}, },
} }

6
go.mod
View File

@@ -5,9 +5,9 @@ go 1.15
require ( require (
github.com/asticode/go-astits v1.10.0 github.com/asticode/go-astits v1.10.0
github.com/icza/bitio v1.0.0 github.com/icza/bitio v1.0.0
github.com/pion/rtcp v1.2.4 github.com/pion/rtcp v1.2.9
github.com/pion/rtp v1.6.1 github.com/pion/rtp v1.7.4
github.com/pion/sdp/v3 v3.0.2 github.com/pion/sdp/v3 v3.0.2
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.7.0
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b golang.org/x/net v0.0.0-20210610132358-84b48f89b13b
) )

11
go.sum
View File

@@ -10,10 +10,10 @@ github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lTo
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.4 h1:NT3H5LkUGgaEapvp0HGik+a+CpflRF7KTD7H+o7OWIM= github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
github.com/pion/rtcp v1.2.4/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
github.com/pion/rtp v1.6.1 h1:2Y2elcVBrahYnHKN2X7rMHX/r1R4TEBMP1LaVu/wNhk= github.com/pion/rtp v1.7.4 h1:4dMbjb1SuynU5OpA3kz1zHK+u+eOCQjW3MAeVHf1ODA=
github.com/pion/rtp v1.6.1/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
github.com/pion/sdp/v3 v3.0.2 h1:UNnSPVaMM+Pdu/mR9UvAyyo6zkdYbKeuOooCwZvTl/g= github.com/pion/sdp/v3 v3.0.2 h1:UNnSPVaMM+Pdu/mR9UvAyyo6zkdYbKeuOooCwZvTl/g=
github.com/pion/sdp/v3 v3.0.2/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk= github.com/pion/sdp/v3 v3.0.2/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk=
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
@@ -21,8 +21,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/pion/rtcp" "github.com/pion/rtcp"
"github.com/pion/rtp"
) )
func randUint32() uint32 { func randUint32() uint32 {
@@ -53,7 +54,7 @@ func New(receiverSSRC *uint32, clockRate int) *RTCPReceiver {
// Report generates a RTCP receiver report. // Report generates a RTCP receiver report.
// It returns nil if no RTCP sender reports have been passed to ProcessPacketRTCP yet. // It returns nil if no RTCP sender reports have been passed to ProcessPacketRTCP yet.
func (rr *RTCPReceiver) Report(ts time.Time) []byte { func (rr *RTCPReceiver) Report(ts time.Time) rtcp.Packet {
rr.mutex.Lock() rr.mutex.Lock()
defer rr.mutex.Unlock() defer rr.mutex.Unlock()
@@ -85,35 +86,25 @@ func (rr *RTCPReceiver) Report(ts time.Time) []byte {
rr.totalLostSinceReport = 0 rr.totalLostSinceReport = 0
rr.totalSinceReport = 0 rr.totalSinceReport = 0
byts, err := report.Marshal() return report
if err != nil {
panic(err)
}
return byts
} }
// ProcessPacketRTP extracts the needed data from RTP packets. // ProcessPacketRTP extracts the needed data from RTP packets.
func (rr *RTCPReceiver) ProcessPacketRTP(ts time.Time, payload []byte) { func (rr *RTCPReceiver) ProcessPacketRTP(ts time.Time, pkt *rtp.Packet) {
rr.mutex.Lock() rr.mutex.Lock()
defer rr.mutex.Unlock() defer rr.mutex.Unlock()
// do not parse the entire packet, extract only the fields we need
if len(payload) >= 8 {
sequenceNumber := uint16(payload[2])<<8 | uint16(payload[3])
rtpTime := uint32(payload[4])<<24 | uint32(payload[5])<<16 | uint32(payload[6])<<8 | uint32(payload[7])
// first packet // first packet
if !rr.firstRTPReceived { if !rr.firstRTPReceived {
rr.firstRTPReceived = true rr.firstRTPReceived = true
rr.totalSinceReport = 1 rr.totalSinceReport = 1
rr.lastSequenceNumber = sequenceNumber rr.lastSequenceNumber = pkt.Header.SequenceNumber
rr.lastRTPTimeRTP = rtpTime rr.lastRTPTimeRTP = pkt.Header.Timestamp
rr.lastRTPTimeTime = ts rr.lastRTPTimeTime = ts
// subsequent packets // subsequent packets
} else { } else {
diff := int32(sequenceNumber) - int32(rr.lastSequenceNumber) diff := int32(pkt.Header.SequenceNumber) - int32(rr.lastSequenceNumber)
// following packet or following packet after an overflow // following packet or following packet after an overflow
if diff > 0 || diff < -0x0FFF { if diff > 0 || diff < -0x0FFF {
@@ -123,7 +114,7 @@ func (rr *RTCPReceiver) ProcessPacketRTP(ts time.Time, payload []byte) {
} }
// detect lost packets // detect lost packets
if sequenceNumber != (rr.lastSequenceNumber + 1) { if pkt.Header.SequenceNumber != (rr.lastSequenceNumber + 1) {
rr.totalLost += uint32(uint16(diff) - 1) rr.totalLost += uint32(uint16(diff) - 1)
rr.totalLostSinceReport += uint32(uint16(diff) - 1) rr.totalLostSinceReport += uint32(uint16(diff) - 1)
@@ -139,37 +130,29 @@ func (rr *RTCPReceiver) ProcessPacketRTP(ts time.Time, payload []byte) {
// 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(pkt.Header.Timestamp) - float64(rr.lastRTPTimeRTP))
if D < 0 { if D < 0 {
D = -D D = -D
} }
rr.jitter += (D - rr.jitter) / 16 rr.jitter += (D - rr.jitter) / 16
rr.totalSinceReport += uint32(uint16(diff)) rr.totalSinceReport += uint32(uint16(diff))
rr.lastSequenceNumber = sequenceNumber rr.lastSequenceNumber = pkt.Header.SequenceNumber
rr.lastRTPTimeRTP = rtpTime rr.lastRTPTimeRTP = pkt.Header.Timestamp
rr.lastRTPTimeTime = ts rr.lastRTPTimeTime = ts
} }
// ignore invalid packets (diff = 0) or reordered packets (diff < 0) // ignore invalid packets (diff = 0) or reordered packets (diff < 0)
} }
} }
}
// ProcessPacketRTCP extracts the needed data from RTCP packets. // ProcessPacketRTCP extracts the needed data from RTCP packets.
func (rr *RTCPReceiver) ProcessPacketRTCP(ts time.Time, payload []byte) { func (rr *RTCPReceiver) ProcessPacketRTCP(ts time.Time, pkt rtcp.Packet) {
if sr, ok := (pkt).(*rtcp.SenderReport); ok {
rr.mutex.Lock() rr.mutex.Lock()
defer rr.mutex.Unlock() defer rr.mutex.Unlock()
// we can afford to unmarshal all RTCP packets
// since they are sent with a frequency much lower than the one of RTP packets
packets, err := rtcp.Unmarshal(payload)
if err == nil {
for _, packet := range packets {
if sr, ok := (packet).(*rtcp.SenderReport); ok {
rr.senderSSRC = sr.SSRC rr.senderSSRC = sr.SSRC
rr.lastSenderReport = uint32(sr.NTPTime >> 16) rr.lastSenderReport = uint32(sr.NTPTime >> 16)
rr.lastSenderReportTime = ts rr.lastSenderReportTime = ts
} }
} }
}
}

View File

@@ -13,7 +13,7 @@ func TestRTCPReceiverBase(t *testing.T) {
v := uint32(0x65f83afb) v := uint32(0x65f83afb)
rr := New(&v, 90000) rr := New(&v, 90000)
require.Equal(t, []byte(nil), rr.Report(time.Now())) require.Equal(t, nil, rr.Report(time.Now()))
srPkt := rtcp.SenderReport{ srPkt := rtcp.SenderReport{
SSRC: 0xba9da416, SSRC: 0xba9da416,
@@ -22,9 +22,8 @@ func TestRTCPReceiverBase(t *testing.T) {
PacketCount: 714, PacketCount: 714,
OctetCount: 859127, OctetCount: 859127,
} }
byts, _ := srPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTCP(ts, byts) rr.ProcessPacketRTCP(ts, &srPkt)
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -37,9 +36,8 @@ func TestRTCPReceiverBase(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -52,9 +50,8 @@ func TestRTCPReceiverBase(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.ReceiverReport{ expectedPkt := rtcp.ReceiverReport{
SSRC: 0x65f83afb, SSRC: 0x65f83afb,
@@ -67,9 +64,8 @@ func TestRTCPReceiverBase(t *testing.T) {
}, },
}, },
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 22, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 22, 0, time.UTC)
require.Equal(t, expected, rr.Report(ts)) require.Equal(t, &expectedPkt, rr.Report(ts))
} }
func TestRTCPReceiverOverflow(t *testing.T) { func TestRTCPReceiverOverflow(t *testing.T) {
@@ -83,9 +79,8 @@ func TestRTCPReceiverOverflow(t *testing.T) {
PacketCount: 714, PacketCount: 714,
OctetCount: 859127, OctetCount: 859127,
} }
byts, _ := srPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTCP(ts, byts) rr.ProcessPacketRTCP(ts, &srPkt)
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -98,9 +93,8 @@ func TestRTCPReceiverOverflow(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -113,9 +107,8 @@ func TestRTCPReceiverOverflow(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.ReceiverReport{ expectedPkt := rtcp.ReceiverReport{
SSRC: 0x65f83afb, SSRC: 0x65f83afb,
@@ -128,9 +121,8 @@ func TestRTCPReceiverOverflow(t *testing.T) {
}, },
}, },
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
require.Equal(t, expected, rr.Report(ts)) require.Equal(t, &expectedPkt, rr.Report(ts))
} }
func TestRTCPReceiverPacketLost(t *testing.T) { func TestRTCPReceiverPacketLost(t *testing.T) {
@@ -144,9 +136,8 @@ func TestRTCPReceiverPacketLost(t *testing.T) {
PacketCount: 714, PacketCount: 714,
OctetCount: 859127, OctetCount: 859127,
} }
byts, _ := srPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTCP(ts, byts) rr.ProcessPacketRTCP(ts, &srPkt)
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -159,9 +150,8 @@ func TestRTCPReceiverPacketLost(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -174,9 +164,8 @@ func TestRTCPReceiverPacketLost(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.ReceiverReport{ expectedPkt := rtcp.ReceiverReport{
SSRC: 0x65f83afb, SSRC: 0x65f83afb,
@@ -194,9 +183,8 @@ func TestRTCPReceiverPacketLost(t *testing.T) {
}, },
}, },
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
require.Equal(t, expected, rr.Report(ts)) require.Equal(t, &expectedPkt, rr.Report(ts))
} }
func TestRTCPReceiverOverflowPacketLost(t *testing.T) { func TestRTCPReceiverOverflowPacketLost(t *testing.T) {
@@ -210,9 +198,8 @@ func TestRTCPReceiverOverflowPacketLost(t *testing.T) {
PacketCount: 714, PacketCount: 714,
OctetCount: 859127, OctetCount: 859127,
} }
byts, _ := srPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTCP(ts, byts) rr.ProcessPacketRTCP(ts, &srPkt)
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -225,9 +212,8 @@ func TestRTCPReceiverOverflowPacketLost(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -240,9 +226,8 @@ func TestRTCPReceiverOverflowPacketLost(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.ReceiverReport{ expectedPkt := rtcp.ReceiverReport{
SSRC: 0x65f83afb, SSRC: 0x65f83afb,
@@ -260,9 +245,8 @@ func TestRTCPReceiverOverflowPacketLost(t *testing.T) {
}, },
}, },
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
require.Equal(t, expected, rr.Report(ts)) require.Equal(t, &expectedPkt, rr.Report(ts))
} }
func TestRTCPReceiverReorderedPackets(t *testing.T) { func TestRTCPReceiverReorderedPackets(t *testing.T) {
@@ -276,9 +260,8 @@ func TestRTCPReceiverReorderedPackets(t *testing.T) {
PacketCount: 714, PacketCount: 714,
OctetCount: 859127, OctetCount: 859127,
} }
byts, _ := srPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTCP(ts, byts) rr.ProcessPacketRTCP(ts, &srPkt)
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -291,9 +274,8 @@ func TestRTCPReceiverReorderedPackets(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -306,9 +288,8 @@ func TestRTCPReceiverReorderedPackets(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.ReceiverReport{ expectedPkt := rtcp.ReceiverReport{
SSRC: 0x65f83afb, SSRC: 0x65f83afb,
@@ -321,9 +302,8 @@ func TestRTCPReceiverReorderedPackets(t *testing.T) {
}, },
}, },
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
require.Equal(t, expected, rr.Report(ts)) require.Equal(t, &expectedPkt, rr.Report(ts))
} }
func TestRTCPReceiverJitter(t *testing.T) { func TestRTCPReceiverJitter(t *testing.T) {
@@ -337,9 +317,8 @@ func TestRTCPReceiverJitter(t *testing.T) {
PacketCount: 714, PacketCount: 714,
OctetCount: 859127, OctetCount: 859127,
} }
byts, _ := srPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTCP(ts, byts) rr.ProcessPacketRTCP(ts, &srPkt)
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -352,9 +331,8 @@ func TestRTCPReceiverJitter(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -367,9 +345,8 @@ func TestRTCPReceiverJitter(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 21, 0, time.UTC)
rr.ProcessPacketRTP(ts, byts) rr.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.ReceiverReport{ expectedPkt := rtcp.ReceiverReport{
SSRC: 0x65f83afb, SSRC: 0x65f83afb,
@@ -383,7 +360,6 @@ func TestRTCPReceiverJitter(t *testing.T) {
}, },
}, },
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 22, 0, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 22, 0, time.UTC)
require.Equal(t, expected, rr.Report(ts)) require.Equal(t, &expectedPkt, rr.Report(ts))
} }

View File

@@ -32,7 +32,7 @@ func New(clockRate int) *RTCPSender {
// Report generates a RTCP sender report. // Report generates a RTCP sender report.
// It returns nil if no packets has been passed to ProcessPacketRTP yet. // It returns nil if no packets has been passed to ProcessPacketRTP yet.
func (rs *RTCPSender) Report(ts time.Time) []byte { func (rs *RTCPSender) Report(ts time.Time) rtcp.Packet {
rs.mutex.Lock() rs.mutex.Lock()
defer rs.mutex.Unlock() defer rs.mutex.Unlock()
@@ -40,7 +40,7 @@ func (rs *RTCPSender) Report(ts time.Time) []byte {
return nil return nil
} }
report := &rtcp.SenderReport{ return &rtcp.SenderReport{
SSRC: rs.senderSSRC, SSRC: rs.senderSSRC,
NTPTime: func() uint64 { NTPTime: func() uint64 {
// seconds since 1st January 1900 // seconds since 1st January 1900
@@ -55,23 +55,13 @@ func (rs *RTCPSender) Report(ts time.Time) []byte {
PacketCount: rs.packetCount, PacketCount: rs.packetCount,
OctetCount: rs.octetCount, OctetCount: rs.octetCount,
} }
byts, err := report.Marshal()
if err != nil {
panic(err)
}
return byts
} }
// ProcessPacketRTP extracts the needed data from RTP packets. // ProcessPacketRTP extracts the needed data from RTP packets.
func (rs *RTCPSender) ProcessPacketRTP(ts time.Time, payload []byte) { func (rs *RTCPSender) ProcessPacketRTP(ts time.Time, pkt *rtp.Packet) {
rs.mutex.Lock() rs.mutex.Lock()
defer rs.mutex.Unlock() defer rs.mutex.Unlock()
pkt := rtp.Packet{}
err := pkt.Unmarshal(payload)
if err == nil {
if !rs.firstRTPReceived { if !rs.firstRTPReceived {
rs.firstRTPReceived = true rs.firstRTPReceived = true
rs.senderSSRC = pkt.SSRC rs.senderSSRC = pkt.SSRC
@@ -84,4 +74,3 @@ func (rs *RTCPSender) ProcessPacketRTP(ts time.Time, payload []byte) {
rs.packetCount++ rs.packetCount++
rs.octetCount += uint32(len(pkt.Payload)) rs.octetCount += uint32(len(pkt.Payload))
} }
}

View File

@@ -12,7 +12,7 @@ import (
func TestRTCPSender(t *testing.T) { func TestRTCPSender(t *testing.T) {
rs := New(90000) rs := New(90000)
require.Equal(t, []byte(nil), rs.Report(time.Now())) require.Equal(t, nil, rs.Report(time.Now()))
rtpPkt := rtp.Packet{ rtpPkt := rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -25,9 +25,8 @@ func TestRTCPSender(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ := rtpPkt.Marshal()
ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC) ts := time.Date(2008, 0o5, 20, 22, 15, 20, 0, time.UTC)
rs.ProcessPacketRTP(ts, byts) rs.ProcessPacketRTP(ts, &rtpPkt)
rtpPkt = rtp.Packet{ rtpPkt = rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
@@ -40,9 +39,8 @@ func TestRTCPSender(t *testing.T) {
}, },
Payload: []byte("\x00\x00"), Payload: []byte("\x00\x00"),
} }
byts, _ = rtpPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 15, 20, 500000000, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 15, 20, 500000000, time.UTC)
rs.ProcessPacketRTP(ts, byts) rs.ProcessPacketRTP(ts, &rtpPkt)
expectedPkt := rtcp.SenderReport{ expectedPkt := rtcp.SenderReport{
SSRC: 0xba9da416, SSRC: 0xba9da416,
@@ -51,7 +49,6 @@ func TestRTCPSender(t *testing.T) {
PacketCount: 2, PacketCount: 2,
OctetCount: 4, OctetCount: 4,
} }
expected, _ := expectedPkt.Marshal()
ts = time.Date(2008, 0o5, 20, 22, 16, 20, 600000000, time.UTC) ts = time.Date(2008, 0o5, 20, 22, 16, 20, 600000000, time.UTC)
require.Equal(t, expected, rs.Report(ts)) require.Equal(t, &expectedPkt, rs.Report(ts))
} }

View File

@@ -1648,7 +1648,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
buf, err := (&rtp.Packet{ buf, err := (&rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
Version: 0x80, Version: 2,
PayloadType: 96, PayloadType: 96,
SequenceNumber: 556, SequenceNumber: 556,
Timestamp: 984512368, Timestamp: 984512368,
@@ -1684,7 +1684,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
buf, err = (&rtp.Packet{ buf, err = (&rtp.Packet{
Header: rtp.Header{ Header: rtp.Header{
Version: 0x80, Version: 2,
PayloadType: 96, PayloadType: 96,
SequenceNumber: 87, SequenceNumber: 87,
Timestamp: 756436454, Timestamp: 756436454,

View File

@@ -355,7 +355,8 @@ func (ss *ServerSession) run() {
for trackID, track := range ss.announcedTracks { for trackID, track := range ss.announcedTracks {
rr := track.rtcpReceiver.Report(now) rr := track.rtcpReceiver.Report(now)
if rr != nil { if rr != nil {
ss.WritePacketRTCP(trackID, rr) byts, _ := rr.Marshal()
ss.WritePacketRTCP(trackID, byts)
} }
} }

View File

@@ -8,6 +8,8 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"github.com/aler9/gortsplib/pkg/multibuffer" "github.com/aler9/gortsplib/pkg/multibuffer"
@@ -194,9 +196,15 @@ func (u *serverUDPListener) runReader() {
} }
func (u *serverUDPListener) processRTP(clientData *clientData, payload []byte) { func (u *serverUDPListener) processRTP(clientData *clientData, payload []byte) {
var pkt rtp.Packet
err := pkt.Unmarshal(payload)
if err != nil {
return
}
now := time.Now() now := time.Now()
atomic.StoreInt64(clientData.ss.udpLastFrameTime, now.Unix()) atomic.StoreInt64(clientData.ss.udpLastFrameTime, now.Unix())
clientData.ss.announcedTracks[clientData.trackID].rtcpReceiver.ProcessPacketRTP(now, payload) clientData.ss.announcedTracks[clientData.trackID].rtcpReceiver.ProcessPacketRTP(now, &pkt)
if h, ok := u.s.Handler.(ServerHandlerOnPacketRTP); ok { if h, ok := u.s.Handler.(ServerHandlerOnPacketRTP); ok {
h.OnPacketRTP(&ServerHandlerOnPacketRTPCtx{ h.OnPacketRTP(&ServerHandlerOnPacketRTPCtx{
@@ -208,10 +216,17 @@ func (u *serverUDPListener) processRTP(clientData *clientData, payload []byte) {
} }
func (u *serverUDPListener) processRTCP(clientData *clientData, payload []byte) { func (u *serverUDPListener) processRTCP(clientData *clientData, payload []byte) {
packets, err := rtcp.Unmarshal(payload)
if err != nil {
return
}
if clientData.isPublishing { if clientData.isPublishing {
now := time.Now() now := time.Now()
atomic.StoreInt64(clientData.ss.udpLastFrameTime, now.Unix()) atomic.StoreInt64(clientData.ss.udpLastFrameTime, now.Unix())
clientData.ss.announcedTracks[clientData.trackID].rtcpReceiver.ProcessPacketRTCP(now, payload) for _, pkt := range packets {
clientData.ss.announcedTracks[clientData.trackID].rtcpReceiver.ProcessPacketRTCP(now, pkt)
}
} }
if h, ok := u.s.Handler.(ServerHandlerOnPacketRTCP); ok { if h, ok := u.s.Handler.(ServerHandlerOnPacketRTCP); ok {