Commit fd6b9f6b authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Limit the video rate when we have large numbers of presenters.

parent ffee8044
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"errors" "errors"
"io" "io"
"log" "log"
"math"
"math/bits" "math/bits"
"os" "os"
"strings" "strings"
...@@ -306,6 +307,9 @@ func addUpConn(c *client, id string) (*upConnection, error) { ...@@ -306,6 +307,9 @@ func addUpConn(c *client, id string) (*upConnection, error) {
} }
u.tracks = append(u.tracks, track) u.tracks = append(u.tracks, track)
done := len(u.tracks) >= u.trackCount done := len(u.tracks) >= u.trackCount
if remote.Kind() == webrtc.RTPCodecTypeVideo {
atomic.AddUint32(&c.group.videoCount, 1)
}
c.mu.Unlock() c.mu.Unlock()
clients := c.group.getClients(c) clients := c.group.getClients(c)
...@@ -464,6 +468,17 @@ func delUpConn(c *client, id string) bool { ...@@ -464,6 +468,17 @@ func delUpConn(c *client, id string) bool {
return false return false
} }
for _, track := range conn.tracks {
if track.track.Kind() == webrtc.RTPCodecTypeVideo {
count := atomic.AddUint32(&c.group.videoCount,
^uint32(0))
if count == ^uint32(0) {
log.Printf("Negative track count!")
atomic.StoreUint32(&c.group.videoCount, 0)
}
}
}
type clientId struct { type clientId struct {
client *client client *client
id string id string
...@@ -707,30 +722,35 @@ func trackKinds(down *downConnection) (audio bool, video bool) { ...@@ -707,30 +722,35 @@ func trackKinds(down *downConnection) (audio bool, video bool) {
return return
} }
func updateUpBitrate(up *upConnection) { func updateUpBitrate(up *upConnection, maxVideoRate uint64) {
now := mono.Microseconds() now := mono.Microseconds()
for _, track := range up.tracks { for _, track := range up.tracks {
track.maxBitrate = ^uint64(0) isvideo := track.track.Kind() == webrtc.RTPCodecTypeVideo
minrate := uint64(minAudioRate)
rate := ^uint64(0)
if isvideo {
minrate = minVideoRate
rate = maxVideoRate
if rate < minrate {
rate = minrate
}
}
local := track.getLocal() local := track.getLocal()
for _, l := range local { for _, l := range local {
bitrate := l.GetMaxBitrate(now) bitrate := l.GetMaxBitrate(now)
if bitrate == ^uint64(0) { if bitrate == ^uint64(0) {
continue continue
} }
if bitrate <= minrate {
isvideo := l.track.Kind() == webrtc.RTPCodecTypeVideo rate = minrate
minrate := uint64(9600) break
if isvideo {
minrate = 384000
}
if bitrate < minrate {
bitrate = minrate
} }
if track.maxBitrate > bitrate { if rate > bitrate {
track.maxBitrate = bitrate rate = bitrate
} }
} }
track.maxBitrate = rate
} }
} }
...@@ -1168,9 +1188,18 @@ func sendRateUpdate(c *client) { ...@@ -1168,9 +1188,18 @@ func sendRateUpdate(c *client) {
} }
rembs := make([]remb, 0) rembs := make([]remb, 0)
maxVideoRate := ^uint64(0)
count := atomic.LoadUint32(&c.group.videoCount)
if count >= 3 {
maxVideoRate = uint64(2000000 / math.Sqrt(float64(count)))
if maxVideoRate < minVideoRate {
maxVideoRate = minVideoRate
}
}
c.mu.Lock() c.mu.Lock()
for _, u := range c.up { for _, u := range c.up {
updateUpBitrate(u) updateUpBitrate(u, maxVideoRate)
for _, t := range u.tracks { for _, t := range u.tracks {
bitrate := t.maxBitrate bitrate := t.maxBitrate
if bitrate == ^uint64(0) { if bitrate == ^uint64(0) {
......
...@@ -162,10 +162,16 @@ type chatHistoryEntry struct { ...@@ -162,10 +162,16 @@ type chatHistoryEntry struct {
me bool me bool
} }
const (
minVideoRate = 38400
minAudioRate = 9600
)
type group struct { type group struct {
name string name string
dead bool dead bool
description *groupDescription description *groupDescription
videoCount uint32
mu sync.Mutex mu sync.Mutex
clients map[string]*client clients map[string]*client
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment