diff --git a/internal/config/webrtc.go b/internal/config/webrtc.go index 8fe40f40..2af7fa35 100644 --- a/internal/config/webrtc.go +++ b/internal/config/webrtc.go @@ -28,6 +28,7 @@ type WebRTC struct { IpRetrievalUrl string EstimatorEnabled bool + EstimatorPassive bool EstimatorInitialBitrate int } @@ -79,6 +80,11 @@ func (WebRTC) Init(cmd *cobra.Command) error { return err } + cmd.PersistentFlags().Bool("webrtc.estimator.passive", false, "passive estimator mode, when it does not switch pipelines, only estimates") + if err := viper.BindPFlag("webrtc.estimator.passive", cmd.PersistentFlags().Lookup("webrtc.estimator.passive")); 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 @@ -154,5 +160,6 @@ func (s *WebRTC) Set() { // bandwidth estimator s.EstimatorEnabled = viper.GetBool("webrtc.estimator.enabled") + s.EstimatorPassive = viper.GetBool("webrtc.estimator.passive") s.EstimatorInitialBitrate = viper.GetInt("webrtc.estimator.initial_bitrate") } diff --git a/internal/webrtc/manager.go b/internal/webrtc/manager.go index 5b2005f1..1b483e31 100644 --- a/internal/webrtc/manager.go +++ b/internal/webrtc/manager.go @@ -316,8 +316,8 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, return nil, err } - // if estimator is disabled, disable video auto - if !manager.config.EstimatorEnabled { + // if estimator is disabled, or in passive mode, disable video auto bitrate + if !manager.config.EstimatorEnabled || manager.config.EstimatorPassive { videoAuto = false } @@ -338,7 +338,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 && estimator != nil { + if peerBitrate == 0 && estimator != nil && !manager.config.EstimatorPassive { peerBitrate = estimator.GetTargetBitrate() manager.logger.Debug(). Int("peer_bitrate", peerBitrate). @@ -423,7 +423,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, for range ticker.C { targetBitrate := estimator.GetTargetBitrate() - manager.metrics.SetReceiverEstimatedMaximumBitrate(session, float64(targetBitrate)) + manager.metrics.SetReceiverEstimatedTargetBitrate(session, float64(targetBitrate)) if connection.ConnectionState() == webrtc.PeerConnectionStateClosed { break @@ -431,7 +431,9 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, if !videoTrack.VideoAuto() { continue } - changeVideoFromBitrate(targetBitrate) + if !manager.config.EstimatorPassive { + changeVideoFromBitrate(targetBitrate) + } } }() } @@ -457,10 +459,11 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, }, iceTrickle: manager.config.ICETrickle, setVideoAuto: func(videoAuto bool) { - if manager.config.EstimatorEnabled { + // if estimator is enabled and not in passive mode, enable video auto bitrate + if manager.config.EstimatorEnabled && !manager.config.EstimatorPassive { videoTrack.SetVideoAuto(videoAuto) } else { - logger.Warn().Msg("estimator is disabled, cannot change video auto") + logger.Warn().Msg("estimator is disabled or in passive mode, cannot change video auto") videoTrack.SetVideoAuto(false) // ensure video auto is disabled } }, @@ -666,7 +669,11 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, bitrate int, } for _, p := range packets { - if rtcpPacket, ok := p.(*rtcp.ReceiverReport); ok { + switch rtcpPacket := p.(type) { + case *rtcp.ReceiverEstimatedMaximumBitrate: // TODO: Deprecated. + manager.metrics.SetReceiverEstimatedMaximumBitrate(session, rtcpPacket.Bitrate) + + case *rtcp.ReceiverReport: l := len(rtcpPacket.Reports) if l > 0 { // use only last report diff --git a/internal/webrtc/metrics.go b/internal/webrtc/metrics.go index 2da28e32..923b791e 100644 --- a/internal/webrtc/metrics.go +++ b/internal/webrtc/metrics.go @@ -27,6 +27,7 @@ type metrics struct { videoIdsMu *sync.Mutex receiverEstimatedMaximumBitrate prometheus.Gauge + receiverEstimatedTargetBitrate prometheus.Gauge receiverReportDelay prometheus.Gauge receiverReportJitter prometheus.Gauge @@ -144,6 +145,15 @@ func (m *metricsCtx) getBySession(session types.Session) metrics { "session_id": session.ID(), }, }), + receiverEstimatedTargetBitrate: promauto.NewGauge(prometheus.GaugeOpts{ + Name: "receiver_estimated_target_bitrate", + Namespace: "neko", + Subsystem: "webrtc", + Help: "Receiver Estimated Target Bitrate using Google's congestion control.", + ConstLabels: map[string]string{ + "session_id": session.ID(), + }, + }), receiverReportDelay: promauto.NewGauge(prometheus.GaugeOpts{ Name: "receiver_report_delay", @@ -327,10 +337,16 @@ func (m *metricsCtx) SetVideoID(session types.Session, videoId string) { } } -func (m *metricsCtx) SetReceiverEstimatedMaximumBitrate(session types.Session, bitrate float64) { +func (m *metricsCtx) SetReceiverEstimatedMaximumBitrate(session types.Session, bitrate float32) { met := m.getBySession(session) - met.receiverEstimatedMaximumBitrate.Set(bitrate) + met.receiverEstimatedMaximumBitrate.Set(float64(bitrate)) +} + +func (m *metricsCtx) SetReceiverEstimatedTargetBitrate(session types.Session, bitrate float64) { + met := m.getBySession(session) + + met.receiverEstimatedTargetBitrate.Set(bitrate) } func (m *metricsCtx) SetReceiverReport(session types.Session, report rtcp.ReceptionReport) { diff --git a/pkg/types/codec/codecs.go b/pkg/types/codec/codecs.go index c71057ba..07f51818 100644 --- a/pkg/types/codec/codecs.go +++ b/pkg/types/codec/codecs.go @@ -8,7 +8,7 @@ import ( var RTCPFeedback = []webrtc.RTCPFeedback{ {Type: webrtc.TypeRTCPFBTransportCC, Parameter: ""}, - {Type: webrtc.TypeRTCPFBGoogREMB, Parameter: ""}, + {Type: webrtc.TypeRTCPFBGoogREMB, Parameter: ""}, // TODO: Deprecated. // https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml#sdp-parameters-19 {Type: webrtc.TypeRTCPFBCCM, Parameter: "fir"},