mirror of
https://github.com/jech/galene.git
synced 2024-11-22 08:35:57 +01:00
Remodularise packet cache.
This commit is contained in:
parent
a233f10b0b
commit
44ae9f82d3
2 changed files with 127 additions and 98 deletions
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue