mirror of
https://github.com/livekit/livekit.git
synced 2026-04-05 08:05:41 +00:00
* Use rtcscore-go to calculate audio/video score Signed-off-by: shishir gowda <shishir@livekit.io> * Get max expected layer and find max actual layer from stream Signed-off-by: shishir gowda <shishir@livekit.io> * Cleanup unused methods Signed-off-by: shishir gowda <shishir@livekit.io> * Cleanup code - address review comments Signed-off-by: shishir gowda <shishir@livekit.io> * get expected layer info instead of just quality Signed-off-by: shishir gowda <shishir@livekit.io> * Move SpatialLayerForQuality to utils/helpers method is required in rtc,sfu and connectionstats pkg Moved to utils/helpers.go to remove cyclic deps Signed-off-by: shishir gowda <shishir@livekit.io> * update tests Signed-off-by: shishir gowda <shishir@livekit.io> * Pick stream stats with max layer Signed-off-by: shishir gowda <shishir@livekit.io> * Update rtcscore-go pkg to make rtt/jitter optional when passing 0, rtcscore-go was setting default values Signed-off-by: shishir gowda <shishir@livekit.io> * update score to rating Signed-off-by: shishir gowda <shishir@livekit.io> * Update rtcscore-go pkg to use simulcast layer info for score Signed-off-by: shishir gowda <shishir@livekit.io> * Update score ratings to reflect rtcscore range Signed-off-by: shishir gowda <shishir@livekit.io> * update test params for new rtcscore Signed-off-by: shishir gowda <shishir@livekit.io> * Delay sending scores to connections only till full data is available first interval can have partial data leading to lower scores Signed-off-by: shishir gowda <shishir@livekit.io> * Check for inf values in quality params Signed-off-by: shishir gowda <shishir@livekit.io> * Clean up initial score calculation. Default to 5 Signed-off-by: shishir gowda <shishir@livekit.io> Co-authored-by: David Zhao <dz@livekit.io>
135 lines
3.2 KiB
Go
135 lines
3.2 KiB
Go
package rtc
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/bep/debounce"
|
|
"github.com/pion/webrtc/v3"
|
|
"go.uber.org/atomic"
|
|
|
|
"github.com/livekit/protocol/livekit"
|
|
|
|
"github.com/livekit/livekit-server/pkg/rtc/types"
|
|
"github.com/livekit/livekit-server/pkg/sfu"
|
|
"github.com/livekit/livekit-server/pkg/utils"
|
|
)
|
|
|
|
const (
|
|
subscriptionDebounceInterval = 100 * time.Millisecond
|
|
)
|
|
|
|
type SubscribedTrackParams struct {
|
|
PublisherID livekit.ParticipantID
|
|
PublisherIdentity livekit.ParticipantIdentity
|
|
SubscriberID livekit.ParticipantID
|
|
SubscriberIdentity livekit.ParticipantIdentity
|
|
MediaTrack types.MediaTrack
|
|
DownTrack *sfu.DownTrack
|
|
AdaptiveStream bool
|
|
}
|
|
|
|
type SubscribedTrack struct {
|
|
params SubscribedTrackParams
|
|
subMuted atomic.Bool
|
|
pubMuted atomic.Bool
|
|
settings atomic.Value // *livekit.UpdateTrackSettings
|
|
|
|
onBind func()
|
|
|
|
debouncer func(func())
|
|
}
|
|
|
|
func NewSubscribedTrack(params SubscribedTrackParams) *SubscribedTrack {
|
|
s := &SubscribedTrack{
|
|
params: params,
|
|
debouncer: debounce.New(subscriptionDebounceInterval),
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func (t *SubscribedTrack) OnBind(f func()) {
|
|
t.onBind = f
|
|
}
|
|
|
|
func (t *SubscribedTrack) Bound() {
|
|
if !t.params.AdaptiveStream {
|
|
t.params.DownTrack.SetMaxSpatialLayer(utils.SpatialLayerForQuality(livekit.VideoQuality_HIGH))
|
|
}
|
|
if t.onBind != nil {
|
|
t.onBind()
|
|
}
|
|
}
|
|
|
|
func (t *SubscribedTrack) ID() livekit.TrackID {
|
|
return livekit.TrackID(t.params.DownTrack.ID())
|
|
}
|
|
|
|
func (t *SubscribedTrack) PublisherID() livekit.ParticipantID {
|
|
return t.params.PublisherID
|
|
}
|
|
|
|
func (t *SubscribedTrack) PublisherIdentity() livekit.ParticipantIdentity {
|
|
return t.params.PublisherIdentity
|
|
}
|
|
|
|
func (t *SubscribedTrack) SubscriberID() livekit.ParticipantID {
|
|
return t.params.SubscriberID
|
|
}
|
|
|
|
func (t *SubscribedTrack) SubscriberIdentity() livekit.ParticipantIdentity {
|
|
return t.params.SubscriberIdentity
|
|
}
|
|
|
|
func (t *SubscribedTrack) DownTrack() *sfu.DownTrack {
|
|
return t.params.DownTrack
|
|
}
|
|
|
|
func (t *SubscribedTrack) MediaTrack() types.MediaTrack {
|
|
return t.params.MediaTrack
|
|
}
|
|
|
|
// has subscriber indicated it wants to mute this track
|
|
func (t *SubscribedTrack) IsMuted() bool {
|
|
return t.subMuted.Load()
|
|
}
|
|
|
|
func (t *SubscribedTrack) SetPublisherMuted(muted bool) {
|
|
t.pubMuted.Store(muted)
|
|
t.updateDownTrackMute()
|
|
}
|
|
|
|
func (t *SubscribedTrack) UpdateSubscriberSettings(settings *livekit.UpdateTrackSettings) {
|
|
prevDisabled := t.subMuted.Swap(settings.Disabled)
|
|
t.settings.Store(settings)
|
|
// avoid frequent changes to mute & video layers, unless it became visible
|
|
if prevDisabled != settings.Disabled && !settings.Disabled {
|
|
t.UpdateVideoLayer()
|
|
} else {
|
|
t.debouncer(t.UpdateVideoLayer)
|
|
}
|
|
}
|
|
|
|
func (t *SubscribedTrack) UpdateVideoLayer() {
|
|
t.updateDownTrackMute()
|
|
if t.DownTrack().Kind() != webrtc.RTPCodecTypeVideo {
|
|
return
|
|
}
|
|
|
|
settings, ok := t.settings.Load().(*livekit.UpdateTrackSettings)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
quality := settings.Quality
|
|
if settings.Width > 0 {
|
|
quality = t.MediaTrack().GetQualityForDimension(settings.Width, settings.Height)
|
|
}
|
|
t.DownTrack().SetMaxSpatialLayer(utils.SpatialLayerForQuality(quality))
|
|
}
|
|
|
|
func (t *SubscribedTrack) updateDownTrackMute() {
|
|
muted := t.subMuted.Load() || t.pubMuted.Load()
|
|
t.DownTrack().Mute(muted)
|
|
}
|