mirror of
https://github.com/lkmio/lkm.git
synced 2025-10-04 23:02:43 +08:00
支持GB28181三种推流
This commit is contained in:
189
jitterbuffer/priority_queue.go
Normal file
189
jitterbuffer/priority_queue.go
Normal file
@@ -0,0 +1,189 @@
|
||||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package jitterbuffer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
// PriorityQueue provides a linked list sorting of RTP packets by SequenceNumber
|
||||
type PriorityQueue struct {
|
||||
next *node
|
||||
length uint16
|
||||
}
|
||||
|
||||
type node struct {
|
||||
val *rtp.Packet
|
||||
next *node
|
||||
prev *node
|
||||
priority uint16
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrInvalidOperation may be returned if a Pop or Find operation is performed on an empty queue
|
||||
ErrInvalidOperation = errors.New("attempt to find or pop on an empty list")
|
||||
// ErrNotFound will be returned if the packet cannot be found in the queue
|
||||
ErrNotFound = errors.New("priority not found")
|
||||
)
|
||||
|
||||
// NewQueue will create a new PriorityQueue whose order relies on monotonically
|
||||
// increasing Sequence Number, wrapping at MaxUint16, so
|
||||
// a packet with sequence number MaxUint16 - 1 will be after 0
|
||||
func NewQueue() *PriorityQueue {
|
||||
return &PriorityQueue{
|
||||
next: nil,
|
||||
length: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func newNode(val *rtp.Packet, priority uint16) *node {
|
||||
return &node{
|
||||
val: val,
|
||||
prev: nil,
|
||||
next: nil,
|
||||
priority: priority,
|
||||
}
|
||||
}
|
||||
|
||||
// Find a packet in the queue with the provided sequence number,
|
||||
// regardless of position (the packet is retained in the queue)
|
||||
func (q *PriorityQueue) Find(sqNum uint16) (*rtp.Packet, error) {
|
||||
next := q.next
|
||||
for next != nil {
|
||||
if next.priority == sqNum {
|
||||
return next.val, nil
|
||||
}
|
||||
next = next.next
|
||||
}
|
||||
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
// Push will insert a packet in to the queue in order of sequence number
|
||||
func (q *PriorityQueue) Push(val *rtp.Packet, priority uint16) {
|
||||
newPq := newNode(val, priority)
|
||||
if q.next == nil {
|
||||
q.next = newPq
|
||||
q.length++
|
||||
return
|
||||
}
|
||||
if priority < q.next.priority {
|
||||
newPq.next = q.next
|
||||
q.next.prev = newPq
|
||||
q.next = newPq
|
||||
q.length++
|
||||
return
|
||||
}
|
||||
head := q.next
|
||||
prev := q.next
|
||||
for head != nil {
|
||||
if priority <= head.priority {
|
||||
break
|
||||
}
|
||||
prev = head
|
||||
head = head.next
|
||||
}
|
||||
if head == nil {
|
||||
if prev != nil {
|
||||
prev.next = newPq
|
||||
}
|
||||
newPq.prev = prev
|
||||
} else {
|
||||
newPq.next = head
|
||||
newPq.prev = prev
|
||||
if prev != nil {
|
||||
prev.next = newPq
|
||||
}
|
||||
head.prev = newPq
|
||||
}
|
||||
q.length++
|
||||
}
|
||||
|
||||
// Length will get the total length of the queue
|
||||
func (q *PriorityQueue) Length() uint16 {
|
||||
return q.length
|
||||
}
|
||||
|
||||
// Pop removes the first element from the queue, regardless
|
||||
// sequence number
|
||||
func (q *PriorityQueue) Pop() (*rtp.Packet, error) {
|
||||
if q.next == nil {
|
||||
return nil, ErrInvalidOperation
|
||||
}
|
||||
val := q.next.val
|
||||
q.length--
|
||||
q.next = q.next.next
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// PopAt removes an element at the specified sequence number (priority)
|
||||
func (q *PriorityQueue) PopAt(sqNum uint16) (*rtp.Packet, error) {
|
||||
if q.next == nil {
|
||||
return nil, ErrInvalidOperation
|
||||
}
|
||||
if q.next.priority == sqNum {
|
||||
val := q.next.val
|
||||
q.next = q.next.next
|
||||
q.length--
|
||||
return val, nil
|
||||
}
|
||||
pos := q.next
|
||||
prev := q.next.prev
|
||||
for pos != nil {
|
||||
if pos.priority == sqNum {
|
||||
val := pos.val
|
||||
prev.next = pos.next
|
||||
if prev.next != nil {
|
||||
prev.next.prev = prev
|
||||
}
|
||||
q.length--
|
||||
return val, nil
|
||||
}
|
||||
prev = pos
|
||||
pos = pos.next
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
// PopAtTimestamp removes and returns a packet at the given RTP Timestamp, regardless
|
||||
// sequence number order
|
||||
func (q *PriorityQueue) PopAtTimestamp(timestamp uint32) (*rtp.Packet, error) {
|
||||
if q.next == nil {
|
||||
return nil, ErrInvalidOperation
|
||||
}
|
||||
if q.next.val.Timestamp == timestamp {
|
||||
val := q.next.val
|
||||
q.next = q.next.next
|
||||
q.length--
|
||||
return val, nil
|
||||
}
|
||||
pos := q.next
|
||||
prev := q.next.prev
|
||||
for pos != nil {
|
||||
if pos.val.Timestamp == timestamp {
|
||||
val := pos.val
|
||||
prev.next = pos.next
|
||||
if prev.next != nil {
|
||||
prev.next.prev = prev
|
||||
}
|
||||
q.length--
|
||||
return val, nil
|
||||
}
|
||||
prev = pos
|
||||
pos = pos.next
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
// Clear will empty a PriorityQueue
|
||||
func (q *PriorityQueue) Clear() {
|
||||
next := q.next
|
||||
q.length = 0
|
||||
for next != nil {
|
||||
next.prev = nil
|
||||
next = next.next
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user