Files
gortsplib/pkg/rtpreorderer/reorderer.go

151 lines
3.1 KiB
Go

// Package rtpreorderer implements a filter to reorder incoming RTP packets.
package rtpreorderer
import (
"github.com/pion/rtp"
)
const (
defaultBufferSize = 64
)
// Reorderer filters incoming RTP packets, in order to
// - order packets
// - remove duplicate packets
//
// Deprecated: merged into rtcpreceiver.Receiver.
type Reorderer struct {
initialized bool
expectedSeqNum uint16
buffer []*rtp.Packet
absPos uint16
negativeCount int
// Maximum number of packets to buffer for reordering
BufferSize int
}
// New allocates a Reorderer.
//
// Deprecated: replaced by Initialize().
func New() *Reorderer {
r := &Reorderer{}
r.Initialize()
return r
}
// Initialize initializes a Reorderer.
func (r *Reorderer) Initialize() {
if r.BufferSize == 0 {
r.BufferSize = defaultBufferSize
}
r.buffer = make([]*rtp.Packet, r.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, uint) {
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 > r.BufferSize {
r.negativeCount = 0
// clear buffer
for i := uint16(0); i < uint16(r.BufferSize); i++ {
p := (r.absPos + i) & (uint16(r.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 >= int16(r.BufferSize) {
n := 1
for i := uint16(0); i < uint16(r.BufferSize); i++ {
p := (r.absPos + i) & (uint16(r.BufferSize) - 1)
if r.buffer[p] != nil {
n++
}
}
ret := make([]*rtp.Packet, n)
pos := 0
for i := uint16(0); i < uint16(r.BufferSize); i++ {
p := (r.absPos + i) & (uint16(r.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, uint(int(relPos) - n + 1)
}
// there's a missing packet
if relPos != 0 {
p := (r.absPos + uint16(relPos)) & (uint16(r.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) & (uint16(r.BufferSize) - 1)
if r.buffer[p] == nil {
break
}
n++
}
ret := make([]*rtp.Packet, n)
ret[0] = pkt
r.absPos++
r.absPos &= (uint16(r.BufferSize) - 1)
for i := uint16(1); i < n; i++ {
ret[i], r.buffer[r.absPos] = r.buffer[r.absPos], nil
r.absPos++
r.absPos &= (uint16(r.BufferSize) - 1)
}
r.expectedSeqNum = pkt.SequenceNumber + n
return ret, 0
}