diff --git a/pkg/rtc/mediatrack.go b/pkg/rtc/mediatrack.go index 8b6d6ed40..35987b748 100644 --- a/pkg/rtc/mediatrack.go +++ b/pkg/rtc/mediatrack.go @@ -366,8 +366,10 @@ func (t *MediaTrack) NumUpTracks() (uint32, uint32) { numExpected := atomic.LoadUint32(&t.numUpTracks) t.maxQualityLock.RLock() - // LK-TODO: take into account t.allSubscribersMuted when turning off layer 0 also - maxSubscribed := uint32(SpatialLayerForQuality(t.maxSubscribedQuality) + 1) + maxSubscribed := uint32(0) + if !t.allSubscribersMuted { + maxSubscribed = uint32(SpatialLayerForQuality(t.maxSubscribedQuality) + 1) + } t.maxQualityLock.RUnlock() if maxSubscribed < numExpected { numExpected = maxSubscribed @@ -818,7 +820,7 @@ func (t *MediaTrack) OnSubscribedMaxQualityChange(f func(trackID livekit.TrackID } func (t *MediaTrack) NotifySubscriberMute(subscriberID livekit.ParticipantID) { - if !t.IsSimulcast() { + if t.Kind() != livekit.TrackType_VIDEO { return } @@ -836,7 +838,7 @@ func (t *MediaTrack) NotifySubscriberMute(subscriberID livekit.ParticipantID) { } func (t *MediaTrack) NotifySubscriberMaxQuality(subscriberID livekit.ParticipantID, quality livekit.VideoQuality) { - if !t.IsSimulcast() { + if t.Kind() != livekit.TrackType_VIDEO { return } @@ -878,7 +880,7 @@ func (t *MediaTrack) stopMaxQualityTimer() { } func (t *MediaTrack) updateQualityChange() { - if t.IsMuted() || !t.IsSimulcast() { + if t.Kind() != livekit.TrackType_VIDEO || t.IsMuted() { return } @@ -902,19 +904,12 @@ func (t *MediaTrack) updateQualityChange() { if allSubscribersMuted { if !t.allSubscribersMuted { notifyMaxExpected = true + maxExpectedSpatialLayer = sfu.InvalidLayerSpatial + t.allSubscribersMuted = true - // LK-TODO: do not set this when turning off LOW also below - t.maxSubscribedQuality = livekit.VideoQuality_LOW - maxExpectedSpatialLayer = SpatialLayerForQuality(t.maxSubscribedQuality) - subscribedQualities = []*livekit.SubscribedQuality{ - // LK-TODO-START - // Restarting layers and subscribers getting video involves several things in the path - // which adds up to a few seconds of latency on re-subscription. Do not turn off the - // base layer till there is a good design to reduce re-subscription delays - // LK-TODO-END - {Quality: livekit.VideoQuality_LOW, Enabled: true}, + {Quality: livekit.VideoQuality_LOW, Enabled: false}, {Quality: livekit.VideoQuality_MEDIUM, Enabled: false}, {Quality: livekit.VideoQuality_HIGH, Enabled: false}, } @@ -923,8 +918,9 @@ func (t *MediaTrack) updateQualityChange() { t.allSubscribersMuted = false if maxSubscribedQuality != t.maxSubscribedQuality { notifyMaxExpected = true + maxExpectedSpatialLayer = SpatialLayerForQuality(maxSubscribedQuality) + t.maxSubscribedQuality = maxSubscribedQuality - maxExpectedSpatialLayer = SpatialLayerForQuality(t.maxSubscribedQuality) subscribedQualities = append(subscribedQualities, &livekit.SubscribedQuality{Quality: livekit.VideoQuality_LOW, Enabled: true}) diff --git a/pkg/rtc/mediatrack_test.go b/pkg/rtc/mediatrack_test.go index 5a5b41418..24475baf7 100644 --- a/pkg/rtc/mediatrack_test.go +++ b/pkg/rtc/mediatrack_test.go @@ -125,7 +125,6 @@ func TestSubscribedMaxQuality(t *testing.T) { }, }, }}) - mt.simulcasted.TrySet(true) mt.NotifySubscriberMaxQuality("s1", livekit.VideoQuality_HIGH) @@ -138,11 +137,10 @@ func TestSubscribedMaxQuality(t *testing.T) { }) // mute all subscribers - // LK-TODO: layer 0 is not disabled mt.NotifySubscriberMute("s1") expectedSubscribedQualities := []*livekit.SubscribedQuality{ - &livekit.SubscribedQuality{Quality: livekit.VideoQuality_LOW, Enabled: true}, + &livekit.SubscribedQuality{Quality: livekit.VideoQuality_LOW, Enabled: false}, &livekit.SubscribedQuality{Quality: livekit.VideoQuality_MEDIUM, Enabled: false}, &livekit.SubscribedQuality{Quality: livekit.VideoQuality_HIGH, Enabled: false}, } @@ -174,7 +172,6 @@ func TestSubscribedMaxQuality(t *testing.T) { }, }, }}) - mt.simulcasted.TrySet(true) actualTrackID := "" actualSubscribedQualities := []*livekit.SubscribedQuality{} @@ -218,19 +215,7 @@ func TestSubscribedMaxQuality(t *testing.T) { require.Equal(t, "v1", actualTrackID) require.EqualValues(t, expectedSubscribedQualities, actualSubscribedQualities) - // muting one should still produce LOW - mt.NotifySubscriberMute("s1") - - expectedSubscribedQualities = []*livekit.SubscribedQuality{ - &livekit.SubscribedQuality{Quality: livekit.VideoQuality_LOW, Enabled: true}, - &livekit.SubscribedQuality{Quality: livekit.VideoQuality_MEDIUM, Enabled: false}, - &livekit.SubscribedQuality{Quality: livekit.VideoQuality_HIGH, Enabled: false}, - } - require.Equal(t, "v1", actualTrackID) - require.EqualValues(t, expectedSubscribedQualities, actualSubscribedQualities) - - // muting "s2" should disable all qualities - // LK-TODO: layer 0 is not disabled + // muting "s2" only should not disable all qualities mt.NotifySubscriberMute("s2") expectedSubscribedQualities = []*livekit.SubscribedQuality{ @@ -240,5 +225,16 @@ func TestSubscribedMaxQuality(t *testing.T) { } require.Equal(t, "v1", actualTrackID) require.EqualValues(t, expectedSubscribedQualities, actualSubscribedQualities) + + // muting "s1" also should disable all qualities + mt.NotifySubscriberMute("s1") + + expectedSubscribedQualities = []*livekit.SubscribedQuality{ + &livekit.SubscribedQuality{Quality: livekit.VideoQuality_LOW, Enabled: false}, + &livekit.SubscribedQuality{Quality: livekit.VideoQuality_MEDIUM, Enabled: false}, + &livekit.SubscribedQuality{Quality: livekit.VideoQuality_HIGH, Enabled: false}, + } + require.Equal(t, "v1", actualTrackID) + require.EqualValues(t, expectedSubscribedQualities, actualSubscribedQualities) }) } diff --git a/pkg/sfu/forwarder.go b/pkg/sfu/forwarder.go index 8a8155a4c..39538acb1 100644 --- a/pkg/sfu/forwarder.go +++ b/pkg/sfu/forwarder.go @@ -137,14 +137,17 @@ func (v VideoLayers) GreaterThan(v2 VideoLayers) bool { } const ( + InvalidLayerSpatial = int32(-1) + InvalidLayerTemporal = int32(-1) + DefaultMaxLayerSpatial = int32(2) DefaultMaxLayerTemporal = int32(3) ) var ( InvalidLayers = VideoLayers{ - spatial: -1, - temporal: -1, + spatial: InvalidLayerSpatial, + temporal: InvalidLayerTemporal, } DefaultMaxLayers = VideoLayers{