mirror of
https://github.com/aler9/gortsplib
synced 2025-10-03 14:26:42 +08:00
134 lines
2.7 KiB
Go
134 lines
2.7 KiB
Go
// Package rtpreorderer implements a filter to reorder incoming RTP packets.
|
|
package rtpreorderer
|
|
|
|
import (
|
|
"github.com/pion/rtp"
|
|
)
|
|
|
|
const (
|
|
bufferSize = 64
|
|
)
|
|
|
|
// Reorderer filters incoming RTP packets, in order to
|
|
// - order packets
|
|
// - remove duplicate packets
|
|
type Reorderer struct {
|
|
initialized bool
|
|
expectedSeqNum uint16
|
|
buffer []*rtp.Packet
|
|
absPos uint16
|
|
negativeCount int
|
|
}
|
|
|
|
// Initialize initializes a Reorderer.
|
|
func (r *Reorderer) Initialize() {
|
|
r.buffer = make([]*rtp.Packet, bufferSize)
|
|
}
|
|
|
|
// Process processes a RTP packet.
|
|
// It returns a sequence of ordered packets and the number of lost packets.
|
|
func (r *Reorderer) Process(pkt *rtp.Packet) ([]*rtp.Packet, uint64) {
|
|
if !r.initialized {
|
|
r.initialized = true
|
|
r.expectedSeqNum = pkt.SequenceNumber + 1
|
|
return []*rtp.Packet{pkt}, 0
|
|
}
|
|
|
|
relPos := int16(pkt.SequenceNumber - r.expectedSeqNum)
|
|
|
|
// packet is a duplicate or has been sent
|
|
// before the first packet processed by Reorderer.
|
|
// discard.
|
|
if relPos < 0 {
|
|
r.negativeCount++
|
|
|
|
// stream has been resetted, therefore reset reorderer too
|
|
if r.negativeCount > bufferSize {
|
|
r.negativeCount = 0
|
|
|
|
// clear buffer
|
|
for i := uint16(0); i < bufferSize; i++ {
|
|
p := (r.absPos + i) & (bufferSize - 1)
|
|
r.buffer[p] = nil
|
|
}
|
|
|
|
// reset position
|
|
r.expectedSeqNum = pkt.SequenceNumber + 1
|
|
return []*rtp.Packet{pkt}, 0
|
|
}
|
|
|
|
return nil, 0
|
|
}
|
|
r.negativeCount = 0
|
|
|
|
// there's a missing packet and buffer is full.
|
|
// return entire buffer and clear it.
|
|
if relPos >= bufferSize {
|
|
n := 1
|
|
for i := uint16(0); i < bufferSize; i++ {
|
|
p := (r.absPos + i) & (bufferSize - 1)
|
|
if r.buffer[p] != nil {
|
|
n++
|
|
}
|
|
}
|
|
|
|
ret := make([]*rtp.Packet, n)
|
|
pos := 0
|
|
|
|
for i := uint16(0); i < bufferSize; i++ {
|
|
p := (r.absPos + i) & (bufferSize - 1)
|
|
if r.buffer[p] != nil {
|
|
ret[pos], r.buffer[p] = r.buffer[p], nil
|
|
pos++
|
|
}
|
|
}
|
|
|
|
ret[pos] = pkt
|
|
|
|
r.expectedSeqNum = pkt.SequenceNumber + 1
|
|
return ret, uint64(int(relPos) - n + 1)
|
|
}
|
|
|
|
// there's a missing packet
|
|
if relPos != 0 {
|
|
p := (r.absPos + uint16(relPos)) & (bufferSize - 1)
|
|
|
|
// current packet is a duplicate. discard
|
|
if r.buffer[p] != nil {
|
|
return nil, 0
|
|
}
|
|
|
|
// put current packet in buffer
|
|
r.buffer[p] = pkt
|
|
return nil, 0
|
|
}
|
|
|
|
// all packets have been received correctly.
|
|
// return them
|
|
|
|
n := uint16(1)
|
|
for {
|
|
p := (r.absPos + n) & (bufferSize - 1)
|
|
if r.buffer[p] == nil {
|
|
break
|
|
}
|
|
n++
|
|
}
|
|
|
|
ret := make([]*rtp.Packet, n)
|
|
|
|
ret[0] = pkt
|
|
r.absPos++
|
|
r.absPos &= (bufferSize - 1)
|
|
|
|
for i := uint16(1); i < n; i++ {
|
|
ret[i], r.buffer[r.absPos] = r.buffer[r.absPos], nil
|
|
r.absPos++
|
|
r.absPos &= (bufferSize - 1)
|
|
}
|
|
|
|
r.expectedSeqNum = pkt.SequenceNumber + n
|
|
|
|
return ret, 0
|
|
}
|