diff --git a/internal/config/webrtc.go b/internal/config/webrtc.go index 126f1d5e..8fe40f40 100644 --- a/internal/config/webrtc.go +++ b/internal/config/webrtc.go @@ -26,6 +26,9 @@ type WebRTC struct { NAT1To1IPs []string IpRetrievalUrl string + + EstimatorEnabled bool + EstimatorInitialBitrate int } func (WebRTC) Init(cmd *cobra.Command) error { @@ -69,6 +72,18 @@ func (WebRTC) Init(cmd *cobra.Command) error { return err } + // bandwidth estimator + + cmd.PersistentFlags().Bool("webrtc.estimator.enabled", false, "enables the bandwidth estimator") + if err := viper.BindPFlag("webrtc.estimator.enabled", cmd.PersistentFlags().Lookup("webrtc.estimator.enabled")); err != nil { + return err + } + + cmd.PersistentFlags().Int("webrtc.estimator.initial_bitrate", 1_000_000, "initial bitrate for the bandwidth estimator") + if err := viper.BindPFlag("webrtc.estimator.initial_bitrate", cmd.PersistentFlags().Lookup("webrtc.estimator.initial_bitrate")); err != nil { + return err + } + return nil } @@ -135,4 +150,9 @@ func (s *WebRTC) Set() { log.Warn().Err(err).Msgf("IP retrieval failed") } } + + // bandwidth estimator + + s.EstimatorEnabled = viper.GetBool("webrtc.estimator.enabled") + s.EstimatorInitialBitrate = viper.GetInt("webrtc.estimator.initial_bitrate") } diff --git a/internal/webrtc/manager.go b/internal/webrtc/manager.go index e25f1c93..1dc0ef96 100644 --- a/internal/webrtc/manager.go +++ b/internal/webrtc/manager.go @@ -211,28 +211,34 @@ func (manager *WebRTCManagerCtx) newPeerConnection(bitrate int, codecs []codec.R // create interceptor registry registry := &interceptor.Registry{} - congestionController, err := cc.NewInterceptor(func() (cc.BandwidthEstimator, error) { - if bitrate == 0 { - bitrate = 1_000_000 + // create bandwidth estimator + estimatorChan := make(chan cc.BandwidthEstimator, 1) + if manager.config.EstimatorEnabled { + congestionController, err := cc.NewInterceptor(func() (cc.BandwidthEstimator, error) { + if bitrate == 0 { + bitrate = manager.config.EstimatorInitialBitrate + } + + return gcc.NewSendSideBWE( + gcc.SendSideBWEInitialBitrate(bitrate), + gcc.SendSideBWEPacer(gcc.NewNoOpPacer()), + ) + }) + if err != nil { + return nil, nil, err } - return gcc.NewSendSideBWE( - gcc.SendSideBWEInitialBitrate(bitrate), - gcc.SendSideBWEPacer(gcc.NewNoOpPacer()), - ) - }) - if err != nil { - return nil, nil, err - } + congestionController.OnNewPeerConnection(func(id string, estimator cc.BandwidthEstimator) { + estimatorChan <- estimator + }) - estimatorChan := make(chan cc.BandwidthEstimator, 1) - congestionController.OnNewPeerConnection(func(id string, estimator cc.BandwidthEstimator) { - estimatorChan <- estimator - }) - - registry.Add(congestionController) - if err = webrtc.ConfigureTWCCHeaderExtensionSender(engine, registry); err != nil { - return nil, nil, err + registry.Add(congestionController) + if err = webrtc.ConfigureTWCCHeaderExtensionSender(engine, registry); err != nil { + return nil, nil, err + } + } else { + // no estimator, send nil + estimatorChan <- nil } if err := webrtc.RegisterDefaultInterceptors(engine, registry); err != nil { @@ -276,7 +282,8 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, return nil, err } - if bitrate == 0 { + // if bitrate is 0, and estimator is enabled, use estimator bitrate + if bitrate == 0 && estimator != nil { bitrate = estimator.GetTargetBitrate() } @@ -309,6 +316,11 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, return nil, err } + // if estimator is disabled, disable video auto + if !manager.config.EstimatorEnabled { + videoAuto = false + } + // video track videoTrack, err := NewTrack(logger, videoCodec, connection, WithVideoAuto(videoAuto)) if err != nil { @@ -321,7 +333,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, changeVideoFromBitrate := func(peerBitrate int) { // when switching from manual to auto bitrate estimation, in case the estimator is // idle (lastBitrate > maxBitrate), we want to go back to the previous estimated bitrate - if peerBitrate == 0 { + if peerBitrate == 0 && estimator != nil { peerBitrate = estimator.GetTargetBitrate() manager.logger.Debug(). Int("peer_bitrate", peerBitrate). @@ -397,24 +409,27 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, // set initial video bitrate changeVideoFromBitrate(bitrate) - // use a ticker to get current client target bitrate - go func() { - ticker := time.NewTicker(bitrateCheckInterval) - defer ticker.Stop() + // if estimator is enabled, use it to change video stream + if estimator != nil { + go func() { + // use a ticker to get current client target bitrate + ticker := time.NewTicker(bitrateCheckInterval) + defer ticker.Stop() - for range ticker.C { - targetBitrate := estimator.GetTargetBitrate() - manager.metrics.SetReceiverEstimatedMaximumBitrate(session, float64(targetBitrate)) + for range ticker.C { + targetBitrate := estimator.GetTargetBitrate() + manager.metrics.SetReceiverEstimatedMaximumBitrate(session, float64(targetBitrate)) - if connection.ConnectionState() == webrtc.PeerConnectionStateClosed { - break + if connection.ConnectionState() == webrtc.PeerConnectionStateClosed { + break + } + if !videoTrack.VideoAuto() { + continue + } + changeVideoFromBitrate(targetBitrate) } - if !videoTrack.VideoAuto() { - continue - } - changeVideoFromBitrate(targetBitrate) - } - }() + }() + } // data channel @@ -435,8 +450,15 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, videoTrack.SetPaused(isPaused) audioTrack.SetPaused(isPaused) }, - iceTrickle: manager.config.ICETrickle, - setVideoAuto: videoTrack.SetVideoAuto, + iceTrickle: manager.config.ICETrickle, + setVideoAuto: func(videoAuto bool) { + if manager.config.EstimatorEnabled { + videoTrack.SetVideoAuto(videoAuto) + } else { + logger.Warn().Msg("estimator is disabled, cannot change video auto") + videoTrack.SetVideoAuto(false) // ensure video auto is disabled + } + }, getVideoAuto: videoTrack.VideoAuto, } diff --git a/internal/websocket/handler/signal.go b/internal/websocket/handler/signal.go index ec1955c0..f596f61d 100644 --- a/internal/websocket/handler/signal.go +++ b/internal/websocket/handler/signal.go @@ -40,6 +40,7 @@ func (h *MessageHandlerCtx) signalRequest(session types.Session, payload *messag } payload.Video = webrtcPeer.GetVideoID() + payload.VideoAuto = webrtcPeer.VideoAuto() } session.Send(