mirror of
https://github.com/aler9/gortsplib
synced 2025-10-21 14:19:36 +08:00
rtcp*: split ProcessFrame into ProcessPacketRTP and ProcessPacketRTCP
This commit is contained in:
@@ -7,8 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtcp"
|
||||
|
||||
"github.com/aler9/gortsplib/pkg/base"
|
||||
)
|
||||
|
||||
func randUint32() uint32 {
|
||||
@@ -53,83 +51,6 @@ func New(receiverSSRC *uint32, clockRate int) *RTCPReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessFrame extracts the needed data from RTP or RTCP packets.
|
||||
func (rr *RTCPReceiver) ProcessFrame(ts time.Time, streamType base.StreamType, payload []byte) {
|
||||
rr.mutex.Lock()
|
||||
defer rr.mutex.Unlock()
|
||||
|
||||
if streamType == base.StreamTypeRTP {
|
||||
// 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 frame
|
||||
if !rr.firstRTPReceived {
|
||||
rr.firstRTPReceived = true
|
||||
rr.totalSinceReport = 1
|
||||
rr.lastSequenceNumber = sequenceNumber
|
||||
rr.lastRTPTimeRTP = rtpTime
|
||||
rr.lastRTPTimeTime = ts
|
||||
|
||||
// subsequent frames
|
||||
} else {
|
||||
diff := int32(sequenceNumber) - int32(rr.lastSequenceNumber)
|
||||
|
||||
// following frame or following frame after an overflow
|
||||
if diff > 0 || diff < -0x0FFF {
|
||||
// overflow
|
||||
if diff < -0x0FFF {
|
||||
rr.sequenceNumberCycles++
|
||||
}
|
||||
|
||||
// detect lost frames
|
||||
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
|
||||
}
|
||||
// ignore invalid frames (diff = 0) or reordered frames (diff < 0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we can afford to unmarshal all RTCP packets
|
||||
// since they are sent with a frequency much lower than the one of RTP packets
|
||||
frames, err := rtcp.Unmarshal(payload)
|
||||
if err == nil {
|
||||
for _, frame := range frames {
|
||||
if sr, ok := (frame).(*rtcp.SenderReport); ok {
|
||||
rr.senderSSRC = sr.SSRC
|
||||
rr.lastSenderReport = uint32(sr.NTPTime >> 16)
|
||||
rr.lastSenderReportTime = ts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Report generates a RTCP receiver report.
|
||||
func (rr *RTCPReceiver) Report(ts time.Time) []byte {
|
||||
rr.mutex.Lock()
|
||||
@@ -165,3 +86,84 @@ func (rr *RTCPReceiver) Report(ts time.Time) []byte {
|
||||
|
||||
return byts
|
||||
}
|
||||
|
||||
// ProcessPacketRTP extracts the needed data from RTP packets.
|
||||
func (rr *RTCPReceiver) ProcessPacketRTP(ts time.Time, payload []byte) {
|
||||
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 frame
|
||||
if !rr.firstRTPReceived {
|
||||
rr.firstRTPReceived = true
|
||||
rr.totalSinceReport = 1
|
||||
rr.lastSequenceNumber = sequenceNumber
|
||||
rr.lastRTPTimeRTP = rtpTime
|
||||
rr.lastRTPTimeTime = ts
|
||||
|
||||
// subsequent frames
|
||||
} else {
|
||||
diff := int32(sequenceNumber) - int32(rr.lastSequenceNumber)
|
||||
|
||||
// following frame or following frame after an overflow
|
||||
if diff > 0 || diff < -0x0FFF {
|
||||
// overflow
|
||||
if diff < -0x0FFF {
|
||||
rr.sequenceNumberCycles++
|
||||
}
|
||||
|
||||
// detect lost frames
|
||||
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
|
||||
}
|
||||
// ignore invalid frames (diff = 0) or reordered frames (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()
|
||||
|
||||
// we can afford to unmarshal all RTCP packets
|
||||
// since they are sent with a frequency much lower than the one of RTP packets
|
||||
frames, err := rtcp.Unmarshal(payload)
|
||||
if err == nil {
|
||||
for _, frame := range frames {
|
||||
if sr, ok := (frame).(*rtcp.SenderReport); ok {
|
||||
rr.senderSSRC = sr.SSRC
|
||||
rr.lastSenderReport = uint32(sr.NTPTime >> 16)
|
||||
rr.lastSenderReportTime = ts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user