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

@@ -7,6 +7,7 @@ import (
"time"
"github.com/pion/rtcp"
"github.com/pion/rtp"
)
func randUint32() uint32 {
@@ -53,7 +54,7 @@ func New(receiverSSRC *uint32, clockRate int) *RTCPReceiver {
// Report generates a RTCP receiver report.
// 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()
defer rr.mutex.Unlock()
@@ -85,91 +86,73 @@ func (rr *RTCPReceiver) Report(ts time.Time) []byte {
rr.totalLostSinceReport = 0
rr.totalSinceReport = 0
byts, err := report.Marshal()
if err != nil {
panic(err)
}
return byts
return report
}
// 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()
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
if !rr.firstRTPReceived {
rr.firstRTPReceived = true
rr.totalSinceReport = 1
rr.lastSequenceNumber = pkt.Header.SequenceNumber
rr.lastRTPTimeRTP = pkt.Header.Timestamp
rr.lastRTPTimeTime = ts
// first packet
if !rr.firstRTPReceived {
rr.firstRTPReceived = true
rr.totalSinceReport = 1
rr.lastSequenceNumber = sequenceNumber
rr.lastRTPTimeRTP = rtpTime
rr.lastRTPTimeTime = ts
// subsequent packets
} else {
diff := int32(pkt.Header.SequenceNumber) - int32(rr.lastSequenceNumber)
// subsequent packets
} else {
diff := int32(sequenceNumber) - int32(rr.lastSequenceNumber)
// following packet or following packet after an overflow
if diff > 0 || diff < -0x0FFF {
// overflow
if diff < -0x0FFF {
rr.sequenceNumberCycles++
}
// detect lost packets
if sequenceNumber != (rr.lastSequenceNumber + 1) {
rr.totalLost += uint32(uint16(diff) - 1)
rr.totalLostSinceReport += uint32(uint16(diff) - 1)
// allow up to 24 bits
if rr.totalLost > 0xFFFFFF {
rr.totalLost = 0xFFFFFF
}
if rr.totalLostSinceReport > 0xFFFFFF {
rr.totalLostSinceReport = 0xFFFFFF
}
}
// compute jitter
// https://tools.ietf.org/html/rfc3550#page-39
D := ts.Sub(rr.lastRTPTimeTime).Seconds()*rr.clockRate -
(float64(rtpTime) - float64(rr.lastRTPTimeRTP))
if D < 0 {
D = -D
}
rr.jitter += (D - rr.jitter) / 16
rr.totalSinceReport += uint32(uint16(diff))
rr.lastSequenceNumber = sequenceNumber
rr.lastRTPTimeRTP = rtpTime
rr.lastRTPTimeTime = ts
// following packet or following packet after an overflow
if diff > 0 || diff < -0x0FFF {
// overflow
if diff < -0x0FFF {
rr.sequenceNumberCycles++
}
// ignore invalid packets (diff = 0) or reordered packets (diff < 0)
// detect lost packets
if pkt.Header.SequenceNumber != (rr.lastSequenceNumber + 1) {
rr.totalLost += uint32(uint16(diff) - 1)
rr.totalLostSinceReport += uint32(uint16(diff) - 1)
// allow up to 24 bits
if rr.totalLost > 0xFFFFFF {
rr.totalLost = 0xFFFFFF
}
if rr.totalLostSinceReport > 0xFFFFFF {
rr.totalLostSinceReport = 0xFFFFFF
}
}
// compute jitter
// https://tools.ietf.org/html/rfc3550#page-39
D := ts.Sub(rr.lastRTPTimeTime).Seconds()*rr.clockRate -
(float64(pkt.Header.Timestamp) - float64(rr.lastRTPTimeRTP))
if D < 0 {
D = -D
}
rr.jitter += (D - rr.jitter) / 16
rr.totalSinceReport += uint32(uint16(diff))
rr.lastSequenceNumber = pkt.Header.SequenceNumber
rr.lastRTPTimeRTP = pkt.Header.Timestamp
rr.lastRTPTimeTime = ts
}
// ignore invalid packets (diff = 0) or reordered packets (diff < 0)
}
}
// ProcessPacketRTCP extracts the needed data from RTCP packets.
func (rr *RTCPReceiver) ProcessPacketRTCP(ts time.Time, payload []byte) {
rr.mutex.Lock()
defer rr.mutex.Unlock()
func (rr *RTCPReceiver) ProcessPacketRTCP(ts time.Time, pkt rtcp.Packet) {
if sr, ok := (pkt).(*rtcp.SenderReport); ok {
rr.mutex.Lock()
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.lastSenderReport = uint32(sr.NTPTime >> 16)
rr.lastSenderReportTime = ts
}
}
rr.senderSSRC = sr.SSRC
rr.lastSenderReport = uint32(sr.NTPTime >> 16)
rr.lastSenderReportTime = ts
}
}

View File

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