mirror of
https://github.com/aler9/gortsplib
synced 2025-10-30 02:01:57 +08:00
client: decode and encode RTP/RTCP packets
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user