1
Fork 0

Take next packet index into account when sending NACKs.

This avoids sending NACKs for packets in the future.
This commit is contained in:
Juliusz Chroboczek 2020-10-04 12:51:56 +02:00
parent 67a821ea75
commit 4a8e48d146
3 changed files with 38 additions and 21 deletions

View File

@ -1,6 +1,7 @@
package packetcache package packetcache
import ( import (
"math/bits"
"sync" "sync"
) )
@ -23,8 +24,9 @@ type Cache struct {
lost uint32 lost uint32
totalLost uint32 totalLost uint32
// bitmap // bitmap
first uint16 bitmapValid bool
bitmap uint32 first uint16
bitmap uint32
// buffered keyframe // buffered keyframe
kfTimestamp uint32 kfTimestamp uint32
kfEntries []entry kfEntries []entry
@ -56,9 +58,10 @@ func seqnoInvalid(seqno, reference uint16) bool {
// Set a bit in the bitmap, shifting first if necessary. // Set a bit in the bitmap, shifting first if necessary.
func (cache *Cache) set(seqno uint16) { func (cache *Cache) set(seqno uint16) {
if cache.bitmap == 0 || seqnoInvalid(seqno, cache.first) { if !cache.bitmapValid || seqnoInvalid(seqno, cache.first) {
cache.first = seqno cache.first = seqno
cache.bitmap = 1 cache.bitmap = 1
cache.bitmapValid = true
return return
} }
@ -66,14 +69,18 @@ func (cache *Cache) set(seqno uint16) {
return return
} }
if seqno-cache.first < 32 { if seqno-cache.first >= 32 {
cache.bitmap |= (1 << uint16(seqno-cache.first)) shift := seqno - cache.first - 31
return cache.bitmap >>= shift
cache.first += shift
}
if (cache.bitmap & 1) == 1 {
ones := bits.TrailingZeros32(^cache.bitmap)
cache.bitmap >>= ones
cache.first += uint16(ones)
} }
shift := seqno - cache.first - 31
cache.bitmap >>= shift
cache.first += shift
cache.bitmap |= (1 << uint16(seqno-cache.first)) cache.bitmap |= (1 << uint16(seqno-cache.first))
return return
} }
@ -262,25 +269,34 @@ func (cache *Cache) ResizeCond(capacity int) bool {
return true return true
} }
// Shift 17 bits out of the bitmap. Return a boolean indicating if any // Shift up to 17 bits out of the bitmap. Return a boolean indicating if
// were 0, the index of the first 0 bit, and a bitmap indicating any // any were 0, the index of the first 0 bit, and a bitmap indicating any
// 0 bits after the first one. // 0 bits after the first one.
func (cache *Cache) BitmapGet() (bool, uint16, uint16) { func (cache *Cache) BitmapGet(next uint16) (bool, uint16, uint16) {
cache.mu.Lock() cache.mu.Lock()
defer cache.mu.Unlock() defer cache.mu.Unlock()
first := cache.first first := cache.first
bitmap := (^cache.bitmap) & 0x1FFFF count := next - first
cache.bitmap >>= 17 if (count&0x8000) != 0 || count == 0 {
cache.first += 17 // next is in the past
return false, first, 0
}
if count > 17 {
count = 17
}
bitmap := (^cache.bitmap) & ^((^uint32(0)) << count)
cache.bitmap >>= count
cache.first += count
if bitmap == 0 { if bitmap == 0 {
return false, first, 0 return false, first, 0
} }
for bitmap&1 == 0 { if (bitmap & 1) == 0 {
bitmap >>= 1 count := bits.TrailingZeros32(bitmap)
first++ bitmap >>= count
first += uint16(count)
} }
return true, first, uint16(bitmap >> 1) return true, first, uint16(bitmap >> 1)

View File

@ -264,7 +264,7 @@ func TestBitmapGet(t *testing.T) {
pos := uint16(42) pos := uint16(42)
for cache.bitmap != 0 { for cache.bitmap != 0 {
found, first, bitmap := cache.BitmapGet() found, first, bitmap := cache.BitmapGet(42 + 65)
if first < pos || first >= pos+64 { if first < pos || first >= pos+64 {
t.Errorf("First is %v, pos is %v", first, pos) t.Errorf("First is %v, pos is %v", first, pos)
} }
@ -304,7 +304,7 @@ func TestBitmapPacket(t *testing.T) {
} }
} }
found, first, bitmap := cache.BitmapGet() found, first, bitmap := cache.BitmapGet(42 + 65)
if !found { if !found {
t.Fatalf("Didn't find any 0 bits") t.Fatalf("Didn't find any 0 bits")

View File

@ -61,7 +61,8 @@ func readLoop(conn *rtpUpConnection, track *rtpUpTrack) {
packet.SequenceNumber, packet.Timestamp, kf, buf[:bytes], packet.SequenceNumber, packet.Timestamp, kf, buf[:bytes],
) )
if packet.SequenceNumber-first > 24 { if packet.SequenceNumber-first > 24 {
found, first, bitmap := track.cache.BitmapGet() found, first, bitmap :=
track.cache.BitmapGet(packet.SequenceNumber - 4)
if found { if found {
err := conn.sendNACK(track, first, bitmap) err := conn.sendNACK(track, first, bitmap)
if err != nil { if err != nil {