From fd6b9f6bdd0c72e2773302831188a16feb2959fe Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Sat, 9 May 2020 12:06:13 +0200 Subject: [PATCH] Limit the video rate when we have large numbers of presenters. --- client.go | 55 ++++++++++++++++++++++++++++++++++++++++++------------- group.go | 6 ++++++ 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/client.go b/client.go index 2525a9c..f7eba74 100644 --- a/client.go +++ b/client.go @@ -10,6 +10,7 @@ import ( "errors" "io" "log" + "math" "math/bits" "os" "strings" @@ -306,6 +307,9 @@ func addUpConn(c *client, id string) (*upConnection, error) { } u.tracks = append(u.tracks, track) done := len(u.tracks) >= u.trackCount + if remote.Kind() == webrtc.RTPCodecTypeVideo { + atomic.AddUint32(&c.group.videoCount, 1) + } c.mu.Unlock() clients := c.group.getClients(c) @@ -464,6 +468,17 @@ func delUpConn(c *client, id string) bool { 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 { client *client id string @@ -707,30 +722,35 @@ func trackKinds(down *downConnection) (audio bool, video bool) { return } -func updateUpBitrate(up *upConnection) { +func updateUpBitrate(up *upConnection, maxVideoRate uint64) { now := mono.Microseconds() 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() for _, l := range local { bitrate := l.GetMaxBitrate(now) if bitrate == ^uint64(0) { continue } - - isvideo := l.track.Kind() == webrtc.RTPCodecTypeVideo - minrate := uint64(9600) - if isvideo { - minrate = 384000 + if bitrate <= minrate { + rate = minrate + break } - if bitrate < minrate { - bitrate = minrate - } - if track.maxBitrate > bitrate { - track.maxBitrate = bitrate + if rate > bitrate { + rate = bitrate } } + track.maxBitrate = rate } } @@ -1168,9 +1188,18 @@ func sendRateUpdate(c *client) { } 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() for _, u := range c.up { - updateUpBitrate(u) + updateUpBitrate(u, maxVideoRate) for _, t := range u.tracks { bitrate := t.maxBitrate if bitrate == ^uint64(0) { diff --git a/group.go b/group.go index bfa6740..14c7740 100644 --- a/group.go +++ b/group.go @@ -162,10 +162,16 @@ type chatHistoryEntry struct { me bool } +const ( + minVideoRate = 38400 + minAudioRate = 9600 +) + type group struct { name string dead bool description *groupDescription + videoCount uint32 mu sync.Mutex clients map[string]*client