mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-04-09 18:45:52 +02:00
60 lines
1.3 KiB
Go
60 lines
1.3 KiB
Go
package kvm
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type VideoBroadcaster struct {
|
|
subscribers map[string]chan []byte
|
|
lock sync.RWMutex
|
|
onFirstSubscribe func()
|
|
onLastUnsubscribe func()
|
|
}
|
|
|
|
var videoBroadcaster = &VideoBroadcaster{
|
|
subscribers: make(map[string]chan []byte),
|
|
}
|
|
|
|
func (b *VideoBroadcaster) Subscribe() (string, chan []byte) {
|
|
b.lock.Lock()
|
|
defer b.lock.Unlock()
|
|
id := uuid.New().String()
|
|
// Buffer a bit to avoid dropping frames too easily,
|
|
// but not too much to avoid latency build-up
|
|
ch := make(chan []byte, 200)
|
|
wasEmpty := len(b.subscribers) == 0
|
|
b.subscribers[id] = ch
|
|
if wasEmpty && b.onFirstSubscribe != nil {
|
|
b.onFirstSubscribe()
|
|
}
|
|
return id, ch
|
|
}
|
|
|
|
func (b *VideoBroadcaster) Unsubscribe(id string) {
|
|
b.lock.Lock()
|
|
defer b.lock.Unlock()
|
|
if ch, ok := b.subscribers[id]; ok {
|
|
close(ch)
|
|
delete(b.subscribers, id)
|
|
if len(b.subscribers) == 0 && b.onLastUnsubscribe != nil {
|
|
b.onLastUnsubscribe()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (b *VideoBroadcaster) Broadcast(data []byte) {
|
|
b.lock.RLock()
|
|
defer b.lock.RUnlock()
|
|
for _, ch := range b.subscribers {
|
|
// Non-blocking send
|
|
select {
|
|
case ch <- data:
|
|
default:
|
|
// Drop frame if channel is full to avoid blocking other subscribers
|
|
// Ideally we should have a ring buffer or similar, but this is simple
|
|
}
|
|
}
|
|
}
|