WebRTC congestion control (#26)

* Add congestion control

* Improve stream matching, add manual stream selection, add metrics

* Use a ticker for bitrate estimation and make bandwidth drops switch to lower streams more aggressively

* Missing signal response, fix video auto bug

* Remove redundant mutex

* Bitrate history queue

* Get bitrate fn support h264 & float64

---------

Co-authored-by: Aleksandar Sukovic <aleksandar.sukovic@gmail.com>
This commit is contained in:
Miroslav Šedivý 2023-02-06 19:45:51 +01:00 committed by GitHub
parent e80ae8019e
commit 2364facd60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 738 additions and 222 deletions

View file

@ -8,6 +8,7 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/demodesk/neko/internal/capture/buckets"
"github.com/demodesk/neko/internal/config"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/types/codec"
@ -22,7 +23,7 @@ type CaptureManagerCtx struct {
broadcast *BroacastManagerCtx
screencast *ScreencastManagerCtx
audio *StreamSinkManagerCtx
video *BucketsManagerCtx
video types.BucketsManager
// sources
webcam *StreamSrcManagerCtx
@ -32,7 +33,7 @@ type CaptureManagerCtx struct {
func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCtx {
logger := log.With().Str("module", "capture").Logger()
videos := map[string]*StreamSinkManagerCtx{}
videos := map[string]types.StreamSinkManager{}
for video_id, cnf := range config.VideoPipelines {
pipelineConf := cnf
@ -68,9 +69,10 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
Msg("syntax check for video stream pipeline passed")
getVideoBitrate := pipelineConf.GetBitrateFn(desktop.GetScreenSize)
if err != nil {
if _, err = getVideoBitrate(); err != nil {
logger.Panic().Err(err).Msg("unable to get video bitrate")
}
// append to videos
videos[video_id] = streamSinkNew(config.VideoCodec, createPipeline, video_id, getVideoBitrate)
}
@ -139,7 +141,7 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
"! appsink name=appsink", config.AudioDevice, config.AudioCodec.Pipeline,
), nil
}, "audio", nil),
video: bucketsNew(config.VideoCodec, videos, config.VideoIDs),
video: buckets.BucketsNew(config.VideoCodec, videos, config.VideoIDs),
// sources
webcam: streamSrcNew(config.WebcamEnabled, map[string]string{
@ -200,7 +202,7 @@ func (manager *CaptureManagerCtx) Start() {
}
manager.desktop.OnBeforeScreenSizeChange(func() {
manager.video.destroyAll()
manager.video.DestroyAll()
if manager.broadcast.Started() {
manager.broadcast.destroyPipeline()
@ -212,7 +214,7 @@ func (manager *CaptureManagerCtx) Start() {
})
manager.desktop.OnAfterScreenSizeChange(func() {
err := manager.video.recreateAll()
err := manager.video.RecreateAll()
if err != nil {
manager.logger.Panic().Err(err).Msg("unable to recreate video pipelines")
}
@ -240,7 +242,7 @@ func (manager *CaptureManagerCtx) Shutdown() error {
manager.screencast.shutdown()
manager.audio.shutdown()
manager.video.shutdown()
manager.video.Shutdown()
manager.webcam.shutdown()
manager.microphone.shutdown()