1
Fork 0

Remodularise packet cache.

This commit is contained in:
Juliusz Chroboczek 2020-10-04 17:08:42 +02:00
parent a233f10b0b
commit 44ae9f82d3
2 changed files with 127 additions and 98 deletions

View File

@ -6,7 +6,7 @@ import (
) )
const BufSize = 1500 const BufSize = 1500
const maxKeyframe = 1024 const maxFrame = 1024
type entry struct { type entry struct {
seqno uint16 seqno uint16
@ -14,6 +14,17 @@ type entry struct {
buf [BufSize]byte buf [BufSize]byte
} }
type bitmap struct {
valid bool
first uint16
bitmap uint32
}
type frame struct {
timestamp uint32
entries []entry
}
type Cache struct { type Cache struct {
mu sync.Mutex mu sync.Mutex
//stats //stats
@ -24,13 +35,10 @@ type Cache struct {
lost uint32 lost uint32
totalLost uint32 totalLost uint32
// bitmap // bitmap
bitmapValid bool bitmap bitmap
first uint16
bitmap uint32
// buffered keyframe // buffered keyframe
kfTimestamp uint32 keyframe frame
kfEntries []entry // the actual cache
// packet cache
tail uint16 tail uint16
entries []entry entries []entry
} }
@ -56,35 +64,118 @@ func seqnoInvalid(seqno, reference uint16) bool {
return false return false
} }
// Set a bit in the bitmap, shifting first if necessary. // set sets a bit in the bitmap, shifting if necessary
func (cache *Cache) set(seqno uint16) { func (bitmap *bitmap) set(seqno uint16) {
if !cache.bitmapValid || seqnoInvalid(seqno, cache.first) { if !bitmap.valid || seqnoInvalid(seqno, bitmap.first) {
cache.first = seqno bitmap.first = seqno
cache.bitmap = 1 bitmap.bitmap = 1
cache.bitmapValid = true bitmap.valid = true
return return
} }
if ((seqno - cache.first) & 0x8000) != 0 { if ((seqno - bitmap.first) & 0x8000) != 0 {
return return
} }
if seqno-cache.first >= 32 { if seqno-bitmap.first >= 32 {
shift := seqno - cache.first - 31 shift := seqno - bitmap.first - 31
cache.bitmap >>= shift bitmap.bitmap >>= shift
cache.first += shift bitmap.first += shift
} }
if (cache.bitmap & 1) == 1 { if (bitmap.bitmap & 1) == 1 {
ones := bits.TrailingZeros32(^cache.bitmap) ones := bits.TrailingZeros32(^bitmap.bitmap)
cache.bitmap >>= ones bitmap.bitmap >>= ones
cache.first += uint16(ones) bitmap.first += uint16(ones)
} }
cache.bitmap |= (1 << uint16(seqno-cache.first)) bitmap.bitmap |= (1 << uint16(seqno-bitmap.first))
return return
} }
// BitmapGet shifts up to 17 bits out of the bitmap. It returns a boolean
// indicating if any were 0, the index of the first 0 bit, and a bitmap
// indicating any 0 bits after the first one.
func (cache *Cache) BitmapGet(next uint16) (bool, uint16, uint16) {
cache.mu.Lock()
defer cache.mu.Unlock()
return cache.bitmap.get(next)
}
func (bitmap *bitmap) get(next uint16) (bool, uint16, uint16) {
first := bitmap.first
count := next - first
if (count&0x8000) != 0 || count == 0 {
// next is in the past
return false, first, 0
}
if count > 17 {
count = 17
}
bm := (^bitmap.bitmap) & ^((^uint32(0)) << count)
bitmap.bitmap >>= count
bitmap.first += count
if bm == 0 {
return false, first, 0
}
if (bm & 1) == 0 {
count := bits.TrailingZeros32(bm)
bm >>= count
first += uint16(count)
}
return true, first, uint16(bm >> 1)
}
func (frame *frame) store(seqno uint16, timestamp uint32, first bool, data []byte) {
if first {
if frame.timestamp != timestamp {
frame.timestamp = timestamp
frame.entries = frame.entries[:0]
}
} else if len(frame.entries) > 0 {
if frame.timestamp != timestamp {
return
}
} else {
return
}
i := 0
for i < len(frame.entries) {
if frame.entries[i].seqno >= seqno {
break
}
i++
}
if i < len(frame.entries) && frame.entries[i].seqno == seqno {
// duplicate
return
}
if len(frame.entries) >= maxFrame {
// overflow
return
}
e := entry{
seqno: seqno,
length: uint16(len(data)),
}
copy(e.buf[:], data)
if i >= len(frame.entries) {
frame.entries = append(frame.entries, e)
return
}
frame.entries = append(frame.entries, entry{})
copy(frame.entries[i+1:], frame.entries[i:])
frame.entries[i] = e
}
// Store a packet, setting bitmap at the same time // Store a packet, setting bitmap at the same time
func (cache *Cache) Store(seqno uint16, timestamp uint32, keyframe bool, buf []byte) (uint16, uint16) { func (cache *Cache) Store(seqno uint16, timestamp uint32, keyframe bool, buf []byte) (uint16, uint16) {
cache.mu.Lock() cache.mu.Lock()
@ -108,38 +199,9 @@ func (cache *Cache) Store(seqno uint16, timestamp uint32, keyframe bool, buf []b
} }
} }
} }
cache.set(seqno) cache.bitmap.set(seqno)
doit := false cache.keyframe.store(seqno, timestamp, keyframe, buf)
if keyframe {
if cache.kfTimestamp != timestamp {
cache.kfTimestamp = timestamp
cache.kfEntries = cache.kfEntries[:0]
}
doit = true
} else if len(cache.kfEntries) > 0 {
doit = cache.kfTimestamp == timestamp
}
if doit {
i := 0
for i < len(cache.kfEntries) {
if cache.kfEntries[i].seqno >= seqno {
break
}
i++
}
if i >= len(cache.kfEntries) || cache.kfEntries[i].seqno != seqno {
if len(cache.kfEntries) >= maxKeyframe {
cache.kfEntries = cache.kfEntries[:maxKeyframe-1]
}
cache.kfEntries = append(cache.kfEntries, entry{})
copy(cache.kfEntries[i+1:], cache.kfEntries[i:])
}
cache.kfEntries[i].seqno = seqno
cache.kfEntries[i].length = uint16(len(buf))
copy(cache.kfEntries[i].buf[:], buf)
}
i := cache.tail i := cache.tail
cache.entries[i].seqno = seqno cache.entries[i].seqno = seqno
@ -147,7 +209,7 @@ func (cache *Cache) Store(seqno uint16, timestamp uint32, keyframe bool, buf []b
cache.entries[i].length = uint16(len(buf)) cache.entries[i].length = uint16(len(buf))
cache.tail = (i + 1) % uint16(len(cache.entries)) cache.tail = (i + 1) % uint16(len(cache.entries))
return cache.first, i return cache.bitmap.first, i
} }
func (cache *Cache) Expect(n int) { func (cache *Cache) Expect(n int) {
@ -176,7 +238,7 @@ func (cache *Cache) Get(seqno uint16, result []byte) uint16 {
cache.mu.Lock() cache.mu.Lock()
defer cache.mu.Unlock() defer cache.mu.Unlock()
n := get(seqno, cache.kfEntries, result) n := get(seqno, cache.keyframe.entries, result)
if n > 0 { if n > 0 {
return n return n
} }
@ -209,11 +271,11 @@ func (cache *Cache) Keyframe() (uint32, []uint16) {
cache.mu.Lock() cache.mu.Lock()
defer cache.mu.Unlock() defer cache.mu.Unlock()
seqnos := make([]uint16, len(cache.kfEntries)) seqnos := make([]uint16, len(cache.keyframe.entries))
for i := range cache.kfEntries { for i := range cache.keyframe.entries {
seqnos[i] = cache.kfEntries[i].seqno seqnos[i] = cache.keyframe.entries[i].seqno
} }
return cache.kfTimestamp, seqnos return cache.keyframe.timestamp, seqnos
} }
func (cache *Cache) resize(capacity int) { func (cache *Cache) resize(capacity int) {
@ -269,39 +331,6 @@ func (cache *Cache) ResizeCond(capacity int) bool {
return true return true
} }
// Shift up to 17 bits out of the bitmap. Return a boolean indicating if
// any were 0, the index of the first 0 bit, and a bitmap indicating any
// 0 bits after the first one.
func (cache *Cache) BitmapGet(next uint16) (bool, uint16, uint16) {
cache.mu.Lock()
defer cache.mu.Unlock()
first := cache.first
count := next - first
if (count&0x8000) != 0 || count == 0 {
// 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 {
return false, first, 0
}
if (bitmap & 1) == 0 {
count := bits.TrailingZeros32(bitmap)
bitmap >>= count
first += uint16(count)
}
return true, first, uint16(bitmap >> 1)
}
func (cache *Cache) GetStats(reset bool) (uint32, uint32, uint32, uint32) { func (cache *Cache) GetStats(reset bool) (uint32, uint32, uint32, uint32) {
cache.mu.Lock() cache.mu.Lock()
defer cache.mu.Unlock() defer cache.mu.Unlock()

View File

@ -223,8 +223,8 @@ func TestBitmap(t *testing.T) {
} }
value >>= uint16(first - 42) value >>= uint16(first - 42)
if uint32(value) != cache.bitmap { if uint32(value) != cache.bitmap.bitmap {
t.Errorf("Got %b, expected %b", cache.bitmap, value) t.Errorf("Got %b, expected %b", cache.bitmap.bitmap, value)
} }
} }
@ -245,8 +245,8 @@ func TestBitmapWrap(t *testing.T) {
} }
value >>= uint16(first - 42) value >>= uint16(first - 42)
if uint32(value) != cache.bitmap { if uint32(value) != cache.bitmap.bitmap {
t.Errorf("Got %b, expected %b", cache.bitmap, value) t.Errorf("Got %b, expected %b", cache.bitmap.bitmap, value)
} }
} }
@ -263,7 +263,7 @@ func TestBitmapGet(t *testing.T) {
} }
pos := uint16(42) pos := uint16(42)
for cache.bitmap != 0 { for cache.bitmap.bitmap != 0 {
found, first, bitmap := cache.BitmapGet(42 + 65) 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)