Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 68 additions & 64 deletions pkg/jitterbuffer/priority_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,41 +65,32 @@
// 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
// Insert at head: empty list or new node has smallest-or-equal priority.
// Using <= ensures equal-priority elements are consistently placed before
// all existing equals, matching the traversal loop's break-on-equal behavior.
cur := q.next
if cur == nil || priority <= cur.priority {
newPq.next = cur
if cur != nil {
cur.prev = newPq
}
q.next = newPq
q.length++

return

Check failure on line 80 in pkg/jitterbuffer/priority_queue.go

View workflow job for this annotation

GitHub Actions / lint / Go

return with no blank line before (nlreturn)
}
head := q.next
prev := q.next
for head != nil {
if priority <= head.priority {
break
}
prev = head
head = head.next

// Traverse to find insertion point; cur is guaranteed non-nil here.
prev := cur
for cur = cur.next; cur != nil && priority > cur.priority; cur = cur.next {
prev = cur
}
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

prev.next = newPq
newPq.prev = prev
newPq.next = cur
if cur != nil {
cur.prev = newPq
}
q.length++
}
Expand All @@ -112,46 +103,57 @@
// Pop removes the first element from the queue, regardless
// sequence number.
func (q *PriorityQueue) Pop() (*rtp.Packet, error) {
if q.next == nil {
head := q.next
if head == nil {
return nil, ErrInvalidOperation
}
val := q.next.val
q.next.val = nil
q.next = head.next
if head.next != nil {
head.next.prev = nil
}
head.next = nil
val := head.val
head.val = nil
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 {
head := q.next
if head == nil {
return nil, ErrInvalidOperation
}
if q.next.priority == sqNum {
val := q.next.val
q.next.val = nil
q.next = q.next.next
if head.priority == sqNum {
q.next = head.next
if head.next != nil {
head.next.prev = nil
}
head.next = nil
val := head.val
head.val = nil
q.length--

return val, nil
}
pos := q.next
prev := q.next.prev
for pos != nil {
// prev is guaranteed non-nil since head didn't match.
prev := head
for pos := head.next; pos != nil; pos = pos.next {
if pos.priority == sqNum {
val := pos.val
pos.val = nil
prev.next = pos.next
if prev.next != nil {
prev.next.prev = prev
if pos.next != nil {
pos.next.prev = prev
}
pos.next = nil
pos.prev = nil
val := pos.val
pos.val = nil
q.length--

return val, nil
}
prev = pos
pos = pos.next
}

return nil, ErrNotFound
Expand All @@ -160,44 +162,46 @@
// 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 {
head := q.next
if head == nil {
return nil, ErrInvalidOperation
}
if q.next.val.Timestamp == timestamp {
val := q.next.val
q.next.val = nil
q.next = q.next.next
if head.val.Timestamp == timestamp {
q.next = head.next
if head.next != nil {
head.next.prev = nil
}
head.next = nil
val := head.val
head.val = nil
q.length--

return val, nil
}
pos := q.next
prev := q.next.prev
for pos != nil {
// prev is guaranteed non-nil since head didn't match.
prev := head
for pos := head.next; pos != nil; pos = pos.next {
if pos.val.Timestamp == timestamp {
val := pos.val
pos.val = nil
prev.next = pos.next
if prev.next != nil {
prev.next.prev = prev
if pos.next != nil {
pos.next.prev = prev
}
pos.next = nil
pos.prev = nil
val := pos.val
pos.val = nil
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.next = nil
q.length = 0
for next != nil {
next.prev = nil
next = next.next
}
}
Loading