diff --git a/go.mod b/go.mod index 3697f001a..efa5002d0 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/jxskiss/base62 v1.1.0 github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 github.com/livekit/mediatransportutil v0.0.0-20250519131108-fb90f5acfded - github.com/livekit/protocol v1.39.2-0.20250612162213-de4c760d0eeb + github.com/livekit/protocol v1.39.3-0.20250613010514-7b9c3ae9e359 github.com/livekit/psrpc v0.6.1-0.20250511053145-465289d72c3c github.com/mackerelio/go-osstat v0.2.5 github.com/magefile/mage v1.15.0 @@ -64,7 +64,7 @@ require ( ) require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250612022732-297b8109523d.1 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250612204948-4001e52a3c94.1 // indirect buf.build/go/protovalidate v0.13.0 // indirect buf.build/go/protoyaml v0.6.0 // indirect cel.dev/expr v0.24.0 // indirect diff --git a/go.sum b/go.sum index 84d53f592..a764444c3 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,5 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 h1:uwSqFkn8DDTzNlaV9TxgSXY5OCaNdb4rH+Axd2FujkE= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250612022732-297b8109523d.1 h1:AGcXSSKkdfFsRk7qvOnl5VsaifpqL2Iwp9Xhmjchvpo= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250612022732-297b8109523d.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= -buf.build/go/protovalidate v0.12.0 h1:4GKJotbspQjRCcqZMGVSuC8SjwZ/FmgtSuKDpKUTZew= -buf.build/go/protovalidate v0.12.0/go.mod h1:q3PFfbzI05LeqxSwq+begW2syjy2Z6hLxZSkP1OH/D0= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250612204948-4001e52a3c94.1 h1:u02KLZ7wlC15LvNhDaxhOxFjYmEtS30Lri5nOaZUomk= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250612204948-4001e52a3c94.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= buf.build/go/protovalidate v0.13.0 h1:t7nC2w79q8M2KaZfFTaXmyFhnYWTPbGFtZS2rebdIQM= buf.build/go/protovalidate v0.13.0/go.mod h1:b0ZWMqcwgx2sa1IXTFT9EpJlMp03ESY4f8t9yulcykg= buf.build/go/protoyaml v0.6.0 h1:Nzz1lvcXF8YgNZXk+voPPwdU8FjDPTUV4ndNTXN0n2w= @@ -173,8 +169,8 @@ github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 h1:9x+U2HGLrSw5AT github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ= github.com/livekit/mediatransportutil v0.0.0-20250519131108-fb90f5acfded h1:ylZPdnlX1RW9Z15SD4mp87vT2D2shsk0hpLJwSPcq3g= github.com/livekit/mediatransportutil v0.0.0-20250519131108-fb90f5acfded/go.mod h1:mSNtYzSf6iY9xM3UX42VEI+STHvMgHmrYzEHPcdhB8A= -github.com/livekit/protocol v1.39.2-0.20250612162213-de4c760d0eeb h1:rDeauaLLiBOnhKxQzytVVv8nLSVs5LPijrAfuA/JXG0= -github.com/livekit/protocol v1.39.2-0.20250612162213-de4c760d0eeb/go.mod h1:6HPISM0bkTXTk9RIaQTCe0IDbomBPz7Jwp+N3w5sqL0= +github.com/livekit/protocol v1.39.3-0.20250613010514-7b9c3ae9e359 h1:eDPaRl7KLKfM66cCgYEjAL7+aCwpSFIOmIBOe2eGdjY= +github.com/livekit/protocol v1.39.3-0.20250613010514-7b9c3ae9e359/go.mod h1:6HPISM0bkTXTk9RIaQTCe0IDbomBPz7Jwp+N3w5sqL0= github.com/livekit/psrpc v0.6.1-0.20250511053145-465289d72c3c h1:WwEr0YBejYbKzk8LSaO9h8h0G9MnE7shyDu8yXQWmEc= github.com/livekit/psrpc v0.6.1-0.20250511053145-465289d72c3c/go.mod h1:kmD+AZPkWu0MaXIMv57jhNlbiSZZ/Jx4bzlxBDVmJes= github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o= diff --git a/pkg/rtc/mediatrack.go b/pkg/rtc/mediatrack.go index a6faf05c8..90e50c0a2 100644 --- a/pkg/rtc/mediatrack.go +++ b/pkg/rtc/mediatrack.go @@ -81,7 +81,6 @@ type MediaTrackParams struct { ForwardStats *sfu.ForwardStats OnTrackEverSubscribed func(livekit.TrackID) ShouldRegressCodec func() bool - Rids buffer.VideoLayersRid } func NewMediaTrack(params MediaTrackParams, ti *livekit.TrackInfo) *MediaTrack { @@ -107,7 +106,6 @@ func NewMediaTrack(params MediaTrackParams, ti *livekit.TrackInfo) *MediaTrack { Telemetry: params.Telemetry, Logger: params.Logger, RegressionTargetCodec: t.regressionTargetCodec, - Rids: params.Rids, }, ti) if ti.Type == livekit.TrackType_AUDIO { @@ -135,7 +133,7 @@ func NewMediaTrack(params MediaTrackParams, ti *livekit.TrackInfo) *MediaTrack { t.dynacastManager.NotifySubscriberMaxQuality( subscriberID, mimeType, - buffer.SpatialLayerToVideoQuality(layer, t.MediaTrackReceiver.TrackInfo()), + buffer.GetVideoQualityForSpatialLayer(layer, t.MediaTrackReceiver.TrackInfo()), ) }, ) @@ -167,7 +165,7 @@ func (t *MediaTrack) OnSubscribedMaxQualityChange( for _, q := range maxSubscribedQualities { receiver := t.Receiver(q.CodecMime) if receiver != nil { - receiver.SetMaxExpectedSpatialLayer(buffer.VideoQualityToSpatialLayer(q.Quality, t.MediaTrackReceiver.TrackInfo())) + receiver.SetMaxExpectedSpatialLayer(buffer.GetSpatialLayerForVideoQuality(q.Quality, t.MediaTrackReceiver.TrackInfo())) } } } @@ -265,7 +263,7 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe t.lock.Lock() var regressCodec bool mimeType := mime.NormalizeMimeType(track.Codec().MimeType) - layer := buffer.RidToSpatialLayer(track.RID(), ti, t.params.Rids) + layer := buffer.GetSpatialLayerForRid(track.RID(), ti) t.params.Logger.Debugw( "AddReceiver", "rid", track.RID(), @@ -273,6 +271,14 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe "ssrc", track.SSRC(), "codec", track.Codec(), ) + logger.Infow( + "AddReceiver", + "rid", track.RID(), + "layer", layer, + "ssrc", track.SSRC(), + "codec", track.Codec(), + "trackInfo", logger.Proto(ti), + ) // REMOVE wr := t.MediaTrackReceiver.Receiver(mimeType) if wr == nil { priority := -1 @@ -304,7 +310,6 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe receiver, track, ti, - t.params.Rids, LoggerWithCodecMime(t.params.Logger, mimeType), t.params.OnRTCP, t.params.VideoConfig.StreamTrackerManager, diff --git a/pkg/rtc/mediatrackreceiver.go b/pkg/rtc/mediatrackreceiver.go index 0e8f1f39b..16140e92f 100644 --- a/pkg/rtc/mediatrackreceiver.go +++ b/pkg/rtc/mediatrackreceiver.go @@ -130,7 +130,6 @@ type MediaTrackReceiverParams struct { Telemetry telemetry.TelemetryService Logger logger.Logger RegressionTargetCodec mime.MimeType - Rids buffer.VideoLayersRid } type MediaTrackReceiver struct { @@ -175,7 +174,7 @@ func NewMediaTrackReceiver(params MediaTrackReceiverParams, ti *livekit.TrackInf } func (t *MediaTrackReceiver) Restart() { - hq := buffer.VideoQualityToSpatialLayer(livekit.VideoQuality_HIGH, t.TrackInfo()) + hq := buffer.GetSpatialLayerForVideoQuality(livekit.VideoQuality_HIGH, t.TrackInfo()) for _, receiver := range t.loadReceivers() { receiver.SetMaxExpectedSpatialLayer(hq) @@ -670,12 +669,12 @@ func (t *MediaTrackReceiver) updateTrackInfoOfReceivers() { func (t *MediaTrackReceiver) SetLayerSsrc(mimeType mime.MimeType, rid string, ssrc uint32) { t.lock.Lock() trackInfo := t.TrackInfoClone() - layer := buffer.RidToSpatialLayer(rid, trackInfo, t.params.Rids) + layer := buffer.GetSpatialLayerForRid(rid, trackInfo) if layer == buffer.InvalidLayerSpatial { // non-simulcast case will not have `rid` layer = 0 } - quality := buffer.SpatialLayerToVideoQuality(layer, trackInfo) + quality := buffer.GetVideoQualityForSpatialLayer(layer, trackInfo) // set video layer ssrc info for i, ci := range trackInfo.Codecs { if mime.NormalizeMimeType(ci.MimeType) != mimeType { @@ -845,7 +844,7 @@ func (t *MediaTrackReceiver) TrackInfoClone() *livekit.TrackInfo { func (t *MediaTrackReceiver) NotifyMaxLayerChange(maxLayer int32) { trackInfo := t.TrackInfo() - quality := buffer.SpatialLayerToVideoQuality(maxLayer, trackInfo) + quality := buffer.GetVideoQualityForSpatialLayer(maxLayer, trackInfo) ti := &livekit.TrackInfo{ Sid: trackInfo.Sid, Type: trackInfo.Type, diff --git a/pkg/rtc/mediatracksubscriptions.go b/pkg/rtc/mediatracksubscriptions.go index 0095171af..58450f240 100644 --- a/pkg/rtc/mediatracksubscriptions.go +++ b/pkg/rtc/mediatracksubscriptions.go @@ -181,7 +181,7 @@ func (t *MediaTrackSubscriptions) AddSubscriber(sub types.LocalParticipant, wr * if !wr.DetermineReceiver(codec) { if t.onSubscriberMaxQualityChange != nil { go func() { - spatial := buffer.VideoQualityToSpatialLayer(livekit.VideoQuality_HIGH, t.params.MediaTrack.ToProto()) + spatial := buffer.GetSpatialLayerForVideoQuality(livekit.VideoQuality_HIGH, t.params.MediaTrack.ToProto()) t.onSubscriberMaxQualityChange(downTrack.SubscriberID(), mime.NormalizeMimeType(codec.MimeType), spatial) }() } diff --git a/pkg/rtc/participant.go b/pkg/rtc/participant.go index d52babad6..4ce28bcc0 100644 --- a/pkg/rtc/participant.go +++ b/pkg/rtc/participant.go @@ -2814,6 +2814,25 @@ func (p *ParticipantImpl) mediaTrackReceived(track sfu.TrackRemote, rtpReceiver // only assign version on a fresh publish, i. e. avoid updating version in scenarios like migration ti.Version = p.params.VersionGenerator.Next().ToProto() } + + if len(sdpRids) != 0 { + for _, layer := range ti.Layers { + layer.SpatialLayer = buffer.VideoQualityToSpatialLayer(layer.Quality, ti) + layer.Rid = buffer.VideoQualityToRid(layer.Quality, ti, sdpRids) + } + + for _, codec := range ti.Codecs { + if !mime.IsMimeTypeStringEqual(codec.MimeType, track.Codec().MimeType) { + continue + } + + for _, layer := range codec.Layers { + layer.SpatialLayer = buffer.VideoQualityToSpatialLayer(layer.Quality, ti) + layer.Rid = buffer.VideoQualityToRid(layer.Quality, ti, sdpRids) + } + } + } + mt = p.addMediaTrack(signalCid, track.ID(), ti, sdpRids) newTrack = true @@ -2938,7 +2957,6 @@ func (p *ParticipantImpl) addMediaTrack(signalCid string, sdpCid string, ti *liv ShouldRegressCodec: func() bool { return p.helper().ShouldRegressCodec() }, - Rids: sdpRids, }, ti) mt.OnSubscribedMaxQualityChange(p.onSubscribedMaxQualityChange) diff --git a/pkg/rtc/subscribedtrack.go b/pkg/rtc/subscribedtrack.go index a45f4e177..35f0b4e85 100644 --- a/pkg/rtc/subscribedtrack.go +++ b/pkg/rtc/subscribedtrack.go @@ -257,7 +257,7 @@ func (t *SubscribedTrack) applySettings() { quality = mt.GetQualityForDimension(t.settings.Width, t.settings.Height) } - spatial = buffer.VideoQualityToSpatialLayer(quality, mt.ToProto()) + spatial = buffer.GetSpatialLayerForVideoQuality(quality, mt.ToProto()) if t.settings.Fps > 0 { temporal = mt.GetTemporalLayerForSpatialFps(spatial, t.settings.Fps, dt.Mime()) } diff --git a/pkg/sfu/buffer/videolayerutils.go b/pkg/sfu/buffer/videolayerutils.go index cdf6c986e..d79b31ac7 100644 --- a/pkg/sfu/buffer/videolayerutils.go +++ b/pkg/sfu/buffer/videolayerutils.go @@ -104,13 +104,13 @@ func RidToSpatialLayer(rid string, trackInfo *livekit.TrackInfo, ridSpace VideoL return 2 case lp[livekit.VideoQuality_LOW] && lp[livekit.VideoQuality_MEDIUM]: - logger.Warnw("unexpected rid f with only two qualities, low and medium", nil, "trackID", trackInfo.Sid, "trackInfo", logger.Proto(trackInfo)) + logger.Warnw("unexpected rid with only two qualities, low and medium", nil, "trackID", trackInfo.Sid, "trackInfo", logger.Proto(trackInfo), "rid", ridSpace[2]) return 1 case lp[livekit.VideoQuality_LOW] && lp[livekit.VideoQuality_HIGH]: - logger.Warnw("unexpected rid f with only two qualities, low and high", nil, "trackID", trackInfo.Sid, "trackInfo", logger.Proto(trackInfo)) + logger.Warnw("unexpected rid with only two qualities, low and high", nil, "trackID", trackInfo.Sid, "trackInfo", logger.Proto(trackInfo), "rid", ridSpace[2]) return 1 case lp[livekit.VideoQuality_MEDIUM] && lp[livekit.VideoQuality_HIGH]: - logger.Warnw("unexpected rid f with only two qualities, medium and high", nil, "trackID", trackInfo.Sid, "trackInfo", logger.Proto(trackInfo)) + logger.Warnw("unexpected rid with only two qualities, medium and high", nil, "trackID", trackInfo.Sid, "trackInfo", logger.Proto(trackInfo), "rid", ridSpace[2]) return 1 default: @@ -330,3 +330,56 @@ func VideoQualityToSpatialLayer(quality livekit.VideoQuality, trackInfo *livekit return InvalidLayerSpatial } + +// SIMULCAST-CODEC-TODO: these need to be codec mime aware if and when each codec suppports different layers +func GetSpatialLayerForRid(rid string, ti *livekit.TrackInfo) int32 { + if rid == "" { + // single layer without RID + return 0 + } + + if ti == nil { + return InvalidLayerSpatial + } + + for _, layer := range ti.Layers { + if layer.Rid == rid { + return layer.SpatialLayer + } + } + + if len(ti.Layers) == 1 { + // single layer without RID + return 0 + } + + return InvalidLayerSpatial +} + +func GetSpatialLayerForVideoQuality(quality livekit.VideoQuality, ti *livekit.TrackInfo) int32 { + if ti == nil { + return InvalidLayerSpatial + } + + for _, layer := range ti.Layers { + if layer.Quality == quality { + return layer.SpatialLayer + } + } + + return InvalidLayerSpatial +} + +func GetVideoQualityForSpatialLayer(spatialLayer int32, ti *livekit.TrackInfo) livekit.VideoQuality { + if spatialLayer == InvalidLayerSpatial || ti == nil { + return livekit.VideoQuality_OFF + } + + for _, layer := range ti.Layers { + if layer.SpatialLayer == spatialLayer { + return layer.Quality + } + } + + return livekit.VideoQuality_OFF +} diff --git a/pkg/sfu/buffer/videolayerutils_test.go b/pkg/sfu/buffer/videolayerutils_test.go index 365b83a5b..3ae8c6efe 100644 --- a/pkg/sfu/buffer/videolayerutils_test.go +++ b/pkg/sfu/buffer/videolayerutils_test.go @@ -440,3 +440,176 @@ func TestVideoQualityToRidConversion(t *testing.T) { }) } } + +func TestGetSpatialLayerForRid(t *testing.T) { + tests := []struct { + name string + trackInfo *livekit.TrackInfo + ridToSpatialLayer map[string]int32 + }{ + { + "no track info", + nil, + map[string]int32{ + QuarterResolution: InvalidLayerSpatial, + HalfResolution: InvalidLayerSpatial, + FullResolution: InvalidLayerSpatial, + }, + }, + { + "no layers", + &livekit.TrackInfo{}, + map[string]int32{ + QuarterResolution: InvalidLayerSpatial, + HalfResolution: InvalidLayerSpatial, + FullResolution: InvalidLayerSpatial, + }, + }, + { + "no rid", + &livekit.TrackInfo{}, + map[string]int32{ + "": 0, + }, + }, + { + "single layer", + &livekit.TrackInfo{ + Layers: []*livekit.VideoLayer{ + {Quality: livekit.VideoQuality_LOW, SpatialLayer: 0}, + }, + }, + map[string]int32{ + QuarterResolution: 0, + HalfResolution: 0, + FullResolution: 0, + }, + }, + { + "layers", + &livekit.TrackInfo{ + Layers: []*livekit.VideoLayer{ + {Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: QuarterResolution}, + {Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: HalfResolution}, + }, + }, + map[string]int32{ + QuarterResolution: 0, + HalfResolution: 1, + FullResolution: InvalidLayerSpatial, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for testRid, expectedSpatialLayer := range test.ridToSpatialLayer { + actualSpatialLayer := GetSpatialLayerForRid(testRid, test.trackInfo) + require.Equal(t, expectedSpatialLayer, actualSpatialLayer) + } + }) + } +} + +func TestGetSpatialLayerForVideoQuality(t *testing.T) { + tests := []struct { + name string + trackInfo *livekit.TrackInfo + videoQualityToSpatialLayer map[livekit.VideoQuality]int32 + }{ + { + "no track info", + nil, + map[livekit.VideoQuality]int32{ + livekit.VideoQuality_LOW: InvalidLayerSpatial, + livekit.VideoQuality_MEDIUM: InvalidLayerSpatial, + livekit.VideoQuality_HIGH: InvalidLayerSpatial, + }, + }, + { + "no layers", + &livekit.TrackInfo{}, + map[livekit.VideoQuality]int32{ + livekit.VideoQuality_LOW: InvalidLayerSpatial, + livekit.VideoQuality_MEDIUM: InvalidLayerSpatial, + livekit.VideoQuality_HIGH: InvalidLayerSpatial, + }, + }, + { + "layers", + &livekit.TrackInfo{ + Layers: []*livekit.VideoLayer{ + {Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: QuarterResolution}, + {Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: HalfResolution}, + }, + }, + map[livekit.VideoQuality]int32{ + livekit.VideoQuality_LOW: 0, + livekit.VideoQuality_MEDIUM: 1, + livekit.VideoQuality_HIGH: InvalidLayerSpatial, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for testVideoQuality, expectedSpatialLayer := range test.videoQualityToSpatialLayer { + actualSpatialLayer := GetSpatialLayerForVideoQuality(testVideoQuality, test.trackInfo) + require.Equal(t, expectedSpatialLayer, actualSpatialLayer) + } + }) + } +} + +func TestGetVideoQualityorSpatialLayer(t *testing.T) { + tests := []struct { + name string + trackInfo *livekit.TrackInfo + spatialLayerToVideoQuality map[int32]livekit.VideoQuality + }{ + { + "no track info", + nil, + map[int32]livekit.VideoQuality{ + InvalidLayerSpatial: livekit.VideoQuality_OFF, + 0: livekit.VideoQuality_OFF, + 1: livekit.VideoQuality_OFF, + 2: livekit.VideoQuality_OFF, + }, + }, + { + "no layers", + &livekit.TrackInfo{}, + map[int32]livekit.VideoQuality{ + InvalidLayerSpatial: livekit.VideoQuality_OFF, + 0: livekit.VideoQuality_OFF, + 1: livekit.VideoQuality_OFF, + 2: livekit.VideoQuality_OFF, + }, + }, + { + "layers", + &livekit.TrackInfo{ + Layers: []*livekit.VideoLayer{ + {Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: QuarterResolution}, + {Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: HalfResolution}, + }, + }, + map[int32]livekit.VideoQuality{ + InvalidLayerSpatial: livekit.VideoQuality_OFF, + 0: livekit.VideoQuality_LOW, + 1: livekit.VideoQuality_MEDIUM, + 2: livekit.VideoQuality_OFF, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for testSpatialLayer, expectedVideoQuality := range test.spatialLayerToVideoQuality { + actualVideoQuality := GetVideoQualityForSpatialLayer(testSpatialLayer, test.trackInfo) + require.Equal(t, expectedVideoQuality, actualVideoQuality) + } + }) + } +} diff --git a/pkg/sfu/receiver.go b/pkg/sfu/receiver.go index 6a2f69cbd..3a3f8503a 100644 --- a/pkg/sfu/receiver.go +++ b/pkg/sfu/receiver.go @@ -177,7 +177,6 @@ type WebRTCReceiver struct { closed atomic.Bool useTrackers bool trackInfo atomic.Pointer[livekit.TrackInfo] - rids buffer.VideoLayersRid onRTCP func([]rtcp.Packet) @@ -252,7 +251,6 @@ func NewWebRTCReceiver( receiver *webrtc.RTPReceiver, track TrackRemote, trackInfo *livekit.TrackInfo, - rids buffer.VideoLayersRid, logger logger.Logger, onRTCP func([]rtcp.Packet), streamTrackerManagerConfig StreamTrackerManagerConfig, @@ -266,7 +264,6 @@ func NewWebRTCReceiver( codec: track.Codec(), codecState: ReceiverCodecStateNormal, kind: track.Kind(), - rids: rids, onRTCP: onRTCP, isSVC: mime.IsMimeTypeStringSVC(track.Codec().MimeType), isRED: mime.IsMimeTypeStringRED(track.Codec().MimeType), @@ -404,7 +401,7 @@ func (w *WebRTCReceiver) AddUpTrack(track TrackRemote, buff *buffer.Buffer) erro layer := int32(0) if w.Kind() == webrtc.RTPCodecTypeVideo && !w.isSVC { - layer = buffer.RidToSpatialLayer(track.RID(), w.trackInfo.Load(), w.rids) + layer = buffer.GetSpatialLayerForRid(track.RID(), w.trackInfo.Load()) } buff.SetLogger(w.logger.WithValues("layer", layer)) buff.SetAudioLevelParams(audio.AudioLevelParams{ @@ -516,8 +513,7 @@ func (w *WebRTCReceiver) notifyMaxExpectedLayer(layer int32) { expectedBitrate := int64(0) for _, vl := range ti.Layers { - l := buffer.VideoQualityToSpatialLayer(vl.Quality, ti) - if l <= layer { + if vl.SpatialLayer <= layer { expectedBitrate += int64(vl.Bitrate) } } diff --git a/pkg/sfu/streamtrackermanager.go b/pkg/sfu/streamtrackermanager.go index 0a4a00f89..0258508ab 100644 --- a/pkg/sfu/streamtrackermanager.go +++ b/pkg/sfu/streamtrackermanager.go @@ -597,9 +597,8 @@ func (s *StreamTrackerManager) maxExpectedLayerFromTrackInfoLocked() { ti := s.trackInfo.Load() if ti != nil { for _, layer := range ti.Layers { - spatialLayer := buffer.VideoQualityToSpatialLayer(layer.Quality, ti) - if spatialLayer > s.maxExpectedLayer { - s.maxExpectedLayer = spatialLayer + if layer.SpatialLayer > s.maxExpectedLayer { + s.maxExpectedLayer = layer.SpatialLayer } } }