diff --git a/go.mod b/go.mod index 1b5f2474d..5dd859378 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-20230125210925-54e8a70427c1 github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6 - github.com/livekit/protocol v1.36.2-0.20250331123911-67af9b92e4ac + github.com/livekit/protocol v1.36.2-0.20250331173645-dbeeaa7e264b github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126 github.com/mackerelio/go-osstat v0.2.5 github.com/magefile/mage v1.15.0 diff --git a/go.sum b/go.sum index b07f337da..3c10ff681 100644 --- a/go.sum +++ b/go.sum @@ -170,8 +170,8 @@ github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkD github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ= github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6 h1:6ZhtnY9I9knfm3ieIPpznQSEU2rDECO8yliW/ANLQ7U= github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6/go.mod h1:36s+wwmU3O40IAhE+MjBWP3W71QRiEE9SfooSBvtBqY= -github.com/livekit/protocol v1.36.2-0.20250331123911-67af9b92e4ac h1:mEb60UmuJdilpY9WbrdA7L1OgdfBKX9SlRa7GuKMYL8= -github.com/livekit/protocol v1.36.2-0.20250331123911-67af9b92e4ac/go.mod h1:WrT/CYRxtMNOVUjnIPm5OjWtEkmreffTeE1PRZwlRg4= +github.com/livekit/protocol v1.36.2-0.20250331173645-dbeeaa7e264b h1:RGti8X/Khmpt5MVVMiQBtzuTAeCHgPVCXr19lhLZXI8= +github.com/livekit/protocol v1.36.2-0.20250331173645-dbeeaa7e264b/go.mod h1:WrT/CYRxtMNOVUjnIPm5OjWtEkmreffTeE1PRZwlRg4= github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126 h1:fzuYpAQbCid7ySPpQWWePfQOWUrs8x6dJ0T3Wl07n+Y= github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126/go.mod h1:X5WtEZ7OnEs72Fi5/J+i0on3964F1aynQpCalcgMqRo= github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o= diff --git a/pkg/rtc/mediatrack.go b/pkg/rtc/mediatrack.go index 6626fd1c5..4be5466c3 100644 --- a/pkg/rtc/mediatrack.go +++ b/pkg/rtc/mediatrack.go @@ -42,6 +42,7 @@ import ( // Implements MediaTrack and PublishedTrack interface type MediaTrack struct { params MediaTrackParams + numUpTracks atomic.Uint32 buffer *buffer.Buffer everSubscribed atomic.Bool @@ -176,27 +177,8 @@ func (t *MediaTrack) NotifySubscriberNodeMaxQuality(nodeID livekit.NodeID, quali } } -func (t *MediaTrack) HasSignalCid(cid string) bool { - if t.params.SignalCid == cid { - return true - } - - for _, c := range t.MediaTrackReceiver.TrackInfo().Codecs { - if c.SignalCid == cid { - return true - } - } - return false -} - -func (t *MediaTrack) SdpCids() []string { - var sdpCids []string - for _, c := range t.MediaTrackReceiver.TrackInfo().Codecs { - if c.SdpCid != "" { - sdpCids = append(sdpCids, c.SdpCid) - } - } - return sdpCids +func (t *MediaTrack) SignalCid() string { + return t.params.SignalCid } func (t *MediaTrack) HasSdpCid(cid string) bool { @@ -204,8 +186,9 @@ func (t *MediaTrack) HasSdpCid(cid string) bool { return true } - for _, c := range t.MediaTrackReceiver.TrackInfo().Codecs { - if c.SdpCid == cid { + ti := t.MediaTrackReceiver.TrackInfoClone() + for _, c := range ti.Codecs { + if c.Cid == cid { return true } } @@ -216,8 +199,12 @@ func (t *MediaTrack) ToProto() *livekit.TrackInfo { return t.MediaTrackReceiver.TrackInfoClone() } +func (t *MediaTrack) UpdateCodecCid(codecs []*livekit.SimulcastCodec) { + t.MediaTrackReceiver.UpdateCodecCid(codecs) +} + // AddReceiver adds a new RTP receiver to the track, returns true when receiver represents a new codec -func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRemote, mid string, isSimulcast bool) bool { +func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRemote, mid string) bool { var newCodec bool ssrc := uint32(track.SSRC()) buff, rtcpReader := t.params.BufferFactory.GetBufferPair(ssrc) @@ -264,7 +251,6 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe } }) - t.MediaTrackReceiver.UpdateCodecInfo(track.Codec().MimeType, track.ID(), isSimulcast) ti := t.MediaTrackReceiver.TrackInfoClone() t.lock.Lock() var regressCodec bool @@ -272,7 +258,6 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe layer := buffer.RidToSpatialLayer(track.RID(), ti) t.params.Logger.Debugw( "AddReceiver", - "cid", track.ID(), "rid", track.RID(), "layer", layer, "ssrc", track.SSRC(), @@ -410,6 +395,12 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe return false } + // LK-TODO: can remove this completely when VideoLayers protocol becomes the default as it has info from client or if we decide to use TrackInfo.Simulcast + if t.numUpTracks.Inc() > 1 || track.RID() != "" { + // cannot only rely on numUpTracks since we fire metadata events immediately after the first layer + t.SetSimulcast(true) + } + var bitrates int if len(ti.Layers) > int(layer) { bitrates = int(ti.Layers[layer].GetBitrate()) diff --git a/pkg/rtc/mediatrackreceiver.go b/pkg/rtc/mediatrackreceiver.go index 245bfd764..2eebea050 100644 --- a/pkg/rtc/mediatrackreceiver.go +++ b/pkg/rtc/mediatrackreceiver.go @@ -498,15 +498,9 @@ func (t *MediaTrackReceiver) SetSimulcast(simulcast bool) { t.lock.Lock() defer t.lock.Unlock() - if t.IsSimulcast() != simulcast { - trackInfo := t.TrackInfoClone() - trackInfo.Simulcast = simulcast - t.trackInfo.Store(trackInfo) - } -} - -func (t *MediaTrackReceiver) HasMultipleSpatialLayers() bool { - return len(t.TrackInfo().Layers) > 1 + trackInfo := t.TrackInfoClone() + trackInfo.Simulcast = simulcast + t.trackInfo.Store(trackInfo) } func (t *MediaTrackReceiver) Name() string { @@ -713,13 +707,13 @@ func (t *MediaTrackReceiver) SetLayerSsrc(mimeType mime.MimeType, rid string, ss t.updateTrackInfoOfReceivers() } -func (t *MediaTrackReceiver) UpdateCodecSignalCid(codecs []*livekit.SimulcastCodec) { +func (t *MediaTrackReceiver) UpdateCodecCid(codecs []*livekit.SimulcastCodec) { t.lock.Lock() trackInfo := t.TrackInfoClone() for _, c := range codecs { for _, origin := range trackInfo.Codecs { if mime.GetMimeTypeCodec(origin.MimeType) == mime.NormalizeMimeTypeCodec(c.Codec) { - origin.SignalCid = c.Cid + origin.Cid = c.Cid break } } @@ -730,32 +724,6 @@ func (t *MediaTrackReceiver) UpdateCodecSignalCid(codecs []*livekit.SimulcastCod t.updateTrackInfoOfReceivers() } -func (t *MediaTrackReceiver) UpdateCodecInfo(mimeType string, cid string, isSimulcast bool) { - t.lock.Lock() - trackInfo := t.TrackInfoClone() - for _, origin := range trackInfo.Codecs { - if mime.IsMimeTypeStringEqual(origin.MimeType, mimeType) { - if origin.SdpCid != "" { - if origin.SdpCid != cid || origin.IsSimulcast != isSimulcast { - t.params.Logger.Warnw( - "uexpected codec info change", nil, - "oldCid", origin.SdpCid, "newCid", cid, - "oldIsSimulcast", origin.IsSimulcast, "newIsSimulcast", isSimulcast, - ) - } - - } - origin.SdpCid = cid - origin.IsSimulcast = isSimulcast - break - } - } - t.trackInfo.Store(trackInfo) - t.lock.Unlock() - - t.updateTrackInfoOfReceivers() -} - func (t *MediaTrackReceiver) UpdateTrackInfo(ti *livekit.TrackInfo) { updateMute := false clonedInfo := utils.CloneProto(ti) diff --git a/pkg/rtc/participant.go b/pkg/rtc/participant.go index 6486c3975..1e0d09d11 100644 --- a/pkg/rtc/participant.go +++ b/pkg/rtc/participant.go @@ -37,7 +37,6 @@ import ( "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" - sdpHelper "github.com/livekit/protocol/sdp" "github.com/livekit/protocol/utils" "github.com/livekit/protocol/utils/guid" @@ -207,8 +206,6 @@ type ParticipantImpl struct { pendingPublishingTracks map[livekit.TrackID]*pendingTrackInfo pendingRemoteTracks []*pendingRemoteTrack - simulcastTrackIds sync.Map - // supported codecs enabledPublishCodecs []*livekit.Codec enabledSubscribeCodecs []*livekit.Codec @@ -873,29 +870,10 @@ func (p *ParticipantImpl) synthesizeAddTrackRequests(offer webrtc.SessionDescrip return nil } -func (p *ParticipantImpl) findAndStoreSimulcastTrackIds(offer webrtc.SessionDescription) { - parsed, err := offer.Unmarshal() - if err != nil { - return - } - - for _, m := range parsed.MediaDescriptions { - if m.MediaName.Media != "video" { - continue - } - if sdpHelper.IsMediaDescriptionSimulcast(m) { - trackID := sdpHelper.GetTrackIDFromMediaDescription(m) - p.simulcastTrackIds.LoadOrStore(trackID, true) - } - } -} - // HandleOffer an offer from remote participant, used when clients make the initial connection func (p *ParticipantImpl) HandleOffer(offer webrtc.SessionDescription) error { p.pubLogger.Debugw("received offer", "transport", livekit.SignalTarget_PUBLISHER, "offer", offer) - p.findAndStoreSimulcastTrackIds(offer) - if p.params.UseOneShotSignallingMode { if err := p.synthesizeAddTrackRequests(offer); err != nil { return err @@ -1081,7 +1059,6 @@ func (p *ParticipantImpl) Close(sendLeave bool, reason types.ParticipantCloseRea p.pendingTracksLock.Lock() p.pendingTracks = make(map[string]*pendingTrackInfo) p.pendingPublishingTracks = make(map[livekit.TrackID]*pendingTrackInfo) - p.simulcastTrackIds.Clear() p.pendingTracksLock.Unlock() p.UpTrackManager.Close(isExpectedToResume) @@ -1760,13 +1737,6 @@ func (p *ParticipantImpl) onSubscriberOffer(offer webrtc.SessionDescription) err func (p *ParticipantImpl) removePublishedTrack(track types.MediaTrack) { p.RemovePublishedTrack(track, false, true) - - if lmt, ok := track.(types.LocalMediaTrack); ok { - for _, sdpCid := range lmt.SdpCids() { - p.simulcastTrackIds.Delete(sdpCid) - } - } - if p.ProtocolVersion().SupportsUnpublish() { p.sendTrackUnpublished(track.ID()) } else { @@ -1810,13 +1780,7 @@ func (p *ParticipantImpl) onMediaTrack(rtcTrack *webrtc.TrackRemote, rtpReceiver codec = codecs[0] fromSdp = true } - p.params.Logger.Debugw( - "onMediaTrack", - "codec", codec, - "payloadType", codec.PayloadType, - "fromSdp", fromSdp, - "parameters", rtpReceiver.GetParameters(), - ) + p.params.Logger.Debugw("onMediaTrack", "codec", codec, "payloadType", codec.PayloadType, "fromSdp", fromSdp, "parameters", rtpReceiver.GetParameters()) var track sfu.TrackRemote = sfu.NewTrackRemoteFromSdp(rtcTrack, codec) publishedTrack, isNewTrack := p.mediaTrackReceived(track, rtpReceiver) @@ -2247,7 +2211,7 @@ func (p *ParticipantImpl) addPendingTrackLocked(req *livekit.AddTrackRequest) *l return nil } - track.(*MediaTrack).UpdateCodecSignalCid(req.SimulcastCodecs) + track.(*MediaTrack).UpdateCodecCid(req.SimulcastCodecs) ti := track.ToProto() return ti } @@ -2287,8 +2251,8 @@ func (p *ParticipantImpl) addPendingTrackLocked(req *livekit.AddTrackRequest) *l if req.Type == livekit.TrackType_VIDEO { // clients not supporting simulcast codecs, synthesise a codec ti.Codecs = append(ti.Codecs, &livekit.SimulcastCodecInfo{ - SignalCid: req.Cid, - Layers: req.Layers, + Cid: req.Cid, + Layers: req.Layers, }) } } else { @@ -2323,9 +2287,9 @@ func (p *ParticipantImpl) addPendingTrackLocked(req *livekit.AddTrackRequest) *l clonedLayers = append(clonedLayers, utils.CloneProto(l)) } ti.Codecs = append(ti.Codecs, &livekit.SimulcastCodecInfo{ - MimeType: mimeType, - SignalCid: codec.Cid, - Layers: clonedLayers, + MimeType: mimeType, + Cid: codec.Cid, + Layers: clonedLayers, }) } } @@ -2449,20 +2413,10 @@ func (p *ParticipantImpl) mediaTrackReceived(track sfu.TrackRemote, rtpReceiver return nil, false } - receiverIsSimulcast := false - cidIsSimulcast, ok := p.simulcastTrackIds.Load(track.ID()) - if ok { - receiverIsSimulcast = cidIsSimulcast.(bool) - } - // use existing media track to handle simulcast var pubTime time.Duration var isMigrated bool mt, ok := p.getPublishedTrackBySdpCid(track.ID()).(*MediaTrack) - if !ok { - // only works for clients using same cid in signal and SDP, so won't work for clients like Firefox - mt, ok = p.getPublishedTrackBySignalCid(track.ID()).(*MediaTrack) - } if !ok { signalCid, ti, migrated, createdAt := p.getPendingTrack(track.ID(), ToProtoTrackKind(track.Kind()), true) if ti == nil { @@ -2501,10 +2455,6 @@ 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() } - // track level simulcast set up only for the primary codec - // assumption: when a new track is created, it is the primary codec that causes that - ti.Simulcast = receiverIsSimulcast - mt = p.addMediaTrack(signalCid, track.ID(), ti) newTrack = true @@ -2517,9 +2467,10 @@ func (p *ParticipantImpl) mediaTrackReceived(track sfu.TrackRemote, rtpReceiver pubTime = time.Since(createdAt) p.dirty.Store(true) } + p.pendingTracksLock.Unlock() - mt.AddReceiver(rtpReceiver, track, mid, receiverIsSimulcast) + mt.AddReceiver(rtpReceiver, track, mid) if newTrack { go func() { @@ -2670,10 +2621,6 @@ func (p *ParticipantImpl) addMediaTrack(signalCid string, sdpCid string, ti *liv ) } - for _, sdpCid := range mt.SdpCids() { - p.simulcastTrackIds.Delete(sdpCid) - } - p.pendingTracksLock.Lock() if pti := p.pendingTracks[signalCid]; pti != nil { p.sendTrackPublished(signalCid, pti.trackInfos[0]) @@ -2746,7 +2693,7 @@ func (p *ParticipantImpl) getPendingTrack(clientId string, kind livekit.TrackTyp for cid, pti := range p.pendingTracks { ti := pti.trackInfos[0] for _, c := range ti.Codecs { - if c.SignalCid == clientId { + if c.Cid == clientId { pendingInfo = pti signalCid = cid break track_loop @@ -2813,8 +2760,7 @@ func (p *ParticipantImpl) setTrackID(cid string, info *livekit.TrackInfo) { func (p *ParticipantImpl) getPublishedTrackBySignalCid(clientId string) types.MediaTrack { for _, publishedTrack := range p.GetPublishedTracks() { - if publishedTrack.(types.LocalMediaTrack).HasSignalCid(clientId) { - p.pubLogger.Debugw("found track by signal cid", "signalCid", clientId, "trackID", publishedTrack.ID()) + if publishedTrack.(types.LocalMediaTrack).SignalCid() == clientId { return publishedTrack } } diff --git a/pkg/rtc/participant_internal_test.go b/pkg/rtc/participant_internal_test.go index dd45cb27d..4c4d12962 100644 --- a/pkg/rtc/participant_internal_test.go +++ b/pkg/rtc/participant_internal_test.go @@ -137,7 +137,7 @@ func TestTrackPublishing(t *testing.T) { sink := p.params.Sink.(*routingfakes.FakeMessageSink) track := &typesfakes.FakeLocalMediaTrack{} - track.HasSignalCidReturns(true) + track.SignalCidReturns("cid") track.ToProtoReturns(&livekit.TrackInfo{}) // directly add to publishedTracks without lock - for testing purpose only p.UpTrackManager.publishedTracks["cid"] = track diff --git a/pkg/rtc/participant_sdp.go b/pkg/rtc/participant_sdp.go index ea01e7a36..59d75ada9 100644 --- a/pkg/rtc/participant_sdp.go +++ b/pkg/rtc/participant_sdp.go @@ -141,12 +141,7 @@ func (p *ParticipantImpl) setCodecPreferencesVideoForPublisher(offer webrtc.Sess } var mimeType string for _, c := range info.Codecs { - // this is reading streamID from SDP which is technically SDP cid, - // but it is not set in TrackInfo by the time this is checked, - // hence the check on signal cid. - // As a result, this will fail for clients that use different cid - // while signalling and while doing negotiation (e. g. Firefox) - if c.SignalCid == streamID { + if c.Cid == streamID { mimeType = c.MimeType break } diff --git a/pkg/rtc/subscriptionmanager_test.go b/pkg/rtc/subscriptionmanager_test.go index 011192da0..a8dfe7032 100644 --- a/pkg/rtc/subscriptionmanager_test.go +++ b/pkg/rtc/subscriptionmanager_test.go @@ -242,7 +242,10 @@ func TestUnsubscribe(t *testing.T) { sm.lock.RLock() subLen := len(sm.subscriptions) sm.lock.RUnlock() - return subLen == 0 + if subLen != 0 { + return false + } + return true }, subSettleTimeout, subCheckInterval, "Track was not unsubscribed") // no traces should be left diff --git a/pkg/rtc/transport.go b/pkg/rtc/transport.go index b2888ddd9..e7d302ae8 100644 --- a/pkg/rtc/transport.go +++ b/pkg/rtc/transport.go @@ -1322,7 +1322,7 @@ func (t *PCTransport) AddTrackToStreamAllocator(subTrack types.SubscribedTrack) t.streamAllocator.AddTrack(subTrack.DownTrack(), streamallocator.AddTrackParams{ Source: subTrack.MediaTrack().Source(), - IsSimulcast: subTrack.MediaTrack().HasMultipleSpatialLayers(), + IsSimulcast: subTrack.MediaTrack().IsSimulcast(), PublisherID: subTrack.MediaTrack().PublisherID(), }) } diff --git a/pkg/rtc/types/interfaces.go b/pkg/rtc/types/interfaces.go index 1d4beecfd..d44bb329c 100644 --- a/pkg/rtc/types/interfaces.go +++ b/pkg/rtc/types/interfaces.go @@ -506,7 +506,6 @@ type MediaTrack interface { SetMuted(muted bool) IsSimulcast() bool - HasMultipleSpatialLayers() bool GetAudioLevel() (level float64, active bool) @@ -543,8 +542,7 @@ type LocalMediaTrack interface { Restart() - HasSignalCid(cid string) bool - SdpCids() []string + SignalCid() string HasSdpCid(cid string) bool GetConnectionScoreAndQuality() (float32, livekit.ConnectionQuality) diff --git a/pkg/rtc/types/typesfakes/fake_local_media_track.go b/pkg/rtc/types/typesfakes/fake_local_media_track.go index 4db6e0923..877267f6c 100644 --- a/pkg/rtc/types/typesfakes/fake_local_media_track.go +++ b/pkg/rtc/types/typesfakes/fake_local_media_track.go @@ -118,16 +118,6 @@ type FakeLocalMediaTrack struct { getTrackStatsReturnsOnCall map[int]struct { result1 *livekit.RTPStats } - HasMultipleSpatialLayersStub func() bool - hasMultipleSpatialLayersMutex sync.RWMutex - hasMultipleSpatialLayersArgsForCall []struct { - } - hasMultipleSpatialLayersReturns struct { - result1 bool - } - hasMultipleSpatialLayersReturnsOnCall map[int]struct { - result1 bool - } HasSdpCidStub func(string) bool hasSdpCidMutex sync.RWMutex hasSdpCidArgsForCall []struct { @@ -139,17 +129,6 @@ type FakeLocalMediaTrack struct { hasSdpCidReturnsOnCall map[int]struct { result1 bool } - HasSignalCidStub func(string) bool - hasSignalCidMutex sync.RWMutex - hasSignalCidArgsForCall []struct { - arg1 string - } - hasSignalCidReturns struct { - result1 bool - } - hasSignalCidReturnsOnCall map[int]struct { - result1 bool - } IDStub func() livekit.TrackID iDMutex sync.RWMutex iDArgsForCall []struct { @@ -308,16 +287,6 @@ type FakeLocalMediaTrack struct { revokeDisallowedSubscribersReturnsOnCall map[int]struct { result1 []livekit.ParticipantIdentity } - SdpCidsStub func() []string - sdpCidsMutex sync.RWMutex - sdpCidsArgsForCall []struct { - } - sdpCidsReturns struct { - result1 []string - } - sdpCidsReturnsOnCall map[int]struct { - result1 []string - } SetMutedStub func(bool) setMutedMutex sync.RWMutex setMutedArgsForCall []struct { @@ -328,6 +297,16 @@ type FakeLocalMediaTrack struct { setRTTArgsForCall []struct { arg1 uint32 } + SignalCidStub func() string + signalCidMutex sync.RWMutex + signalCidArgsForCall []struct { + } + signalCidReturns struct { + result1 string + } + signalCidReturnsOnCall map[int]struct { + result1 string + } SourceStub func() livekit.TrackSource sourceMutex sync.RWMutex sourceArgsForCall []struct { @@ -933,59 +912,6 @@ func (fake *FakeLocalMediaTrack) GetTrackStatsReturnsOnCall(i int, result1 *live }{result1} } -func (fake *FakeLocalMediaTrack) HasMultipleSpatialLayers() bool { - fake.hasMultipleSpatialLayersMutex.Lock() - ret, specificReturn := fake.hasMultipleSpatialLayersReturnsOnCall[len(fake.hasMultipleSpatialLayersArgsForCall)] - fake.hasMultipleSpatialLayersArgsForCall = append(fake.hasMultipleSpatialLayersArgsForCall, struct { - }{}) - stub := fake.HasMultipleSpatialLayersStub - fakeReturns := fake.hasMultipleSpatialLayersReturns - fake.recordInvocation("HasMultipleSpatialLayers", []interface{}{}) - fake.hasMultipleSpatialLayersMutex.Unlock() - if stub != nil { - return stub() - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeLocalMediaTrack) HasMultipleSpatialLayersCallCount() int { - fake.hasMultipleSpatialLayersMutex.RLock() - defer fake.hasMultipleSpatialLayersMutex.RUnlock() - return len(fake.hasMultipleSpatialLayersArgsForCall) -} - -func (fake *FakeLocalMediaTrack) HasMultipleSpatialLayersCalls(stub func() bool) { - fake.hasMultipleSpatialLayersMutex.Lock() - defer fake.hasMultipleSpatialLayersMutex.Unlock() - fake.HasMultipleSpatialLayersStub = stub -} - -func (fake *FakeLocalMediaTrack) HasMultipleSpatialLayersReturns(result1 bool) { - fake.hasMultipleSpatialLayersMutex.Lock() - defer fake.hasMultipleSpatialLayersMutex.Unlock() - fake.HasMultipleSpatialLayersStub = nil - fake.hasMultipleSpatialLayersReturns = struct { - result1 bool - }{result1} -} - -func (fake *FakeLocalMediaTrack) HasMultipleSpatialLayersReturnsOnCall(i int, result1 bool) { - fake.hasMultipleSpatialLayersMutex.Lock() - defer fake.hasMultipleSpatialLayersMutex.Unlock() - fake.HasMultipleSpatialLayersStub = nil - if fake.hasMultipleSpatialLayersReturnsOnCall == nil { - fake.hasMultipleSpatialLayersReturnsOnCall = make(map[int]struct { - result1 bool - }) - } - fake.hasMultipleSpatialLayersReturnsOnCall[i] = struct { - result1 bool - }{result1} -} - func (fake *FakeLocalMediaTrack) HasSdpCid(arg1 string) bool { fake.hasSdpCidMutex.Lock() ret, specificReturn := fake.hasSdpCidReturnsOnCall[len(fake.hasSdpCidArgsForCall)] @@ -1047,67 +973,6 @@ func (fake *FakeLocalMediaTrack) HasSdpCidReturnsOnCall(i int, result1 bool) { }{result1} } -func (fake *FakeLocalMediaTrack) HasSignalCid(arg1 string) bool { - fake.hasSignalCidMutex.Lock() - ret, specificReturn := fake.hasSignalCidReturnsOnCall[len(fake.hasSignalCidArgsForCall)] - fake.hasSignalCidArgsForCall = append(fake.hasSignalCidArgsForCall, struct { - arg1 string - }{arg1}) - stub := fake.HasSignalCidStub - fakeReturns := fake.hasSignalCidReturns - fake.recordInvocation("HasSignalCid", []interface{}{arg1}) - fake.hasSignalCidMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeLocalMediaTrack) HasSignalCidCallCount() int { - fake.hasSignalCidMutex.RLock() - defer fake.hasSignalCidMutex.RUnlock() - return len(fake.hasSignalCidArgsForCall) -} - -func (fake *FakeLocalMediaTrack) HasSignalCidCalls(stub func(string) bool) { - fake.hasSignalCidMutex.Lock() - defer fake.hasSignalCidMutex.Unlock() - fake.HasSignalCidStub = stub -} - -func (fake *FakeLocalMediaTrack) HasSignalCidArgsForCall(i int) string { - fake.hasSignalCidMutex.RLock() - defer fake.hasSignalCidMutex.RUnlock() - argsForCall := fake.hasSignalCidArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeLocalMediaTrack) HasSignalCidReturns(result1 bool) { - fake.hasSignalCidMutex.Lock() - defer fake.hasSignalCidMutex.Unlock() - fake.HasSignalCidStub = nil - fake.hasSignalCidReturns = struct { - result1 bool - }{result1} -} - -func (fake *FakeLocalMediaTrack) HasSignalCidReturnsOnCall(i int, result1 bool) { - fake.hasSignalCidMutex.Lock() - defer fake.hasSignalCidMutex.Unlock() - fake.HasSignalCidStub = nil - if fake.hasSignalCidReturnsOnCall == nil { - fake.hasSignalCidReturnsOnCall = make(map[int]struct { - result1 bool - }) - } - fake.hasSignalCidReturnsOnCall[i] = struct { - result1 bool - }{result1} -} - func (fake *FakeLocalMediaTrack) ID() livekit.TrackID { fake.iDMutex.Lock() ret, specificReturn := fake.iDReturnsOnCall[len(fake.iDArgsForCall)] @@ -1970,59 +1835,6 @@ func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersReturnsOnCall(i int, }{result1} } -func (fake *FakeLocalMediaTrack) SdpCids() []string { - fake.sdpCidsMutex.Lock() - ret, specificReturn := fake.sdpCidsReturnsOnCall[len(fake.sdpCidsArgsForCall)] - fake.sdpCidsArgsForCall = append(fake.sdpCidsArgsForCall, struct { - }{}) - stub := fake.SdpCidsStub - fakeReturns := fake.sdpCidsReturns - fake.recordInvocation("SdpCids", []interface{}{}) - fake.sdpCidsMutex.Unlock() - if stub != nil { - return stub() - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeLocalMediaTrack) SdpCidsCallCount() int { - fake.sdpCidsMutex.RLock() - defer fake.sdpCidsMutex.RUnlock() - return len(fake.sdpCidsArgsForCall) -} - -func (fake *FakeLocalMediaTrack) SdpCidsCalls(stub func() []string) { - fake.sdpCidsMutex.Lock() - defer fake.sdpCidsMutex.Unlock() - fake.SdpCidsStub = stub -} - -func (fake *FakeLocalMediaTrack) SdpCidsReturns(result1 []string) { - fake.sdpCidsMutex.Lock() - defer fake.sdpCidsMutex.Unlock() - fake.SdpCidsStub = nil - fake.sdpCidsReturns = struct { - result1 []string - }{result1} -} - -func (fake *FakeLocalMediaTrack) SdpCidsReturnsOnCall(i int, result1 []string) { - fake.sdpCidsMutex.Lock() - defer fake.sdpCidsMutex.Unlock() - fake.SdpCidsStub = nil - if fake.sdpCidsReturnsOnCall == nil { - fake.sdpCidsReturnsOnCall = make(map[int]struct { - result1 []string - }) - } - fake.sdpCidsReturnsOnCall[i] = struct { - result1 []string - }{result1} -} - func (fake *FakeLocalMediaTrack) SetMuted(arg1 bool) { fake.setMutedMutex.Lock() fake.setMutedArgsForCall = append(fake.setMutedArgsForCall, struct { @@ -2087,6 +1899,59 @@ func (fake *FakeLocalMediaTrack) SetRTTArgsForCall(i int) uint32 { return argsForCall.arg1 } +func (fake *FakeLocalMediaTrack) SignalCid() string { + fake.signalCidMutex.Lock() + ret, specificReturn := fake.signalCidReturnsOnCall[len(fake.signalCidArgsForCall)] + fake.signalCidArgsForCall = append(fake.signalCidArgsForCall, struct { + }{}) + stub := fake.SignalCidStub + fakeReturns := fake.signalCidReturns + fake.recordInvocation("SignalCid", []interface{}{}) + fake.signalCidMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeLocalMediaTrack) SignalCidCallCount() int { + fake.signalCidMutex.RLock() + defer fake.signalCidMutex.RUnlock() + return len(fake.signalCidArgsForCall) +} + +func (fake *FakeLocalMediaTrack) SignalCidCalls(stub func() string) { + fake.signalCidMutex.Lock() + defer fake.signalCidMutex.Unlock() + fake.SignalCidStub = stub +} + +func (fake *FakeLocalMediaTrack) SignalCidReturns(result1 string) { + fake.signalCidMutex.Lock() + defer fake.signalCidMutex.Unlock() + fake.SignalCidStub = nil + fake.signalCidReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeLocalMediaTrack) SignalCidReturnsOnCall(i int, result1 string) { + fake.signalCidMutex.Lock() + defer fake.signalCidMutex.Unlock() + fake.SignalCidStub = nil + if fake.signalCidReturnsOnCall == nil { + fake.signalCidReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.signalCidReturnsOnCall[i] = struct { + result1 string + }{result1} +} + func (fake *FakeLocalMediaTrack) Source() livekit.TrackSource { fake.sourceMutex.Lock() ret, specificReturn := fake.sourceReturnsOnCall[len(fake.sourceArgsForCall)] @@ -2367,12 +2232,8 @@ func (fake *FakeLocalMediaTrack) Invocations() map[string][][]interface{} { defer fake.getTemporalLayerForSpatialFpsMutex.RUnlock() fake.getTrackStatsMutex.RLock() defer fake.getTrackStatsMutex.RUnlock() - fake.hasMultipleSpatialLayersMutex.RLock() - defer fake.hasMultipleSpatialLayersMutex.RUnlock() fake.hasSdpCidMutex.RLock() defer fake.hasSdpCidMutex.RUnlock() - fake.hasSignalCidMutex.RLock() - defer fake.hasSignalCidMutex.RUnlock() fake.iDMutex.RLock() defer fake.iDMutex.RUnlock() fake.isEncryptedMutex.RLock() @@ -2409,12 +2270,12 @@ func (fake *FakeLocalMediaTrack) Invocations() map[string][][]interface{} { defer fake.restartMutex.RUnlock() fake.revokeDisallowedSubscribersMutex.RLock() defer fake.revokeDisallowedSubscribersMutex.RUnlock() - fake.sdpCidsMutex.RLock() - defer fake.sdpCidsMutex.RUnlock() fake.setMutedMutex.RLock() defer fake.setMutedMutex.RUnlock() fake.setRTTMutex.RLock() defer fake.setRTTMutex.RUnlock() + fake.signalCidMutex.RLock() + defer fake.signalCidMutex.RUnlock() fake.sourceMutex.RLock() defer fake.sourceMutex.RUnlock() fake.streamMutex.RLock() diff --git a/pkg/rtc/types/typesfakes/fake_media_track.go b/pkg/rtc/types/typesfakes/fake_media_track.go index 9bef455ca..67304714d 100644 --- a/pkg/rtc/types/typesfakes/fake_media_track.go +++ b/pkg/rtc/types/typesfakes/fake_media_track.go @@ -96,16 +96,6 @@ type FakeMediaTrack struct { getTemporalLayerForSpatialFpsReturnsOnCall map[int]struct { result1 int32 } - HasMultipleSpatialLayersStub func() bool - hasMultipleSpatialLayersMutex sync.RWMutex - hasMultipleSpatialLayersArgsForCall []struct { - } - hasMultipleSpatialLayersReturns struct { - result1 bool - } - hasMultipleSpatialLayersReturnsOnCall map[int]struct { - result1 bool - } IDStub func() livekit.TrackID iDMutex sync.RWMutex iDArgsForCall []struct { @@ -749,59 +739,6 @@ func (fake *FakeMediaTrack) GetTemporalLayerForSpatialFpsReturnsOnCall(i int, re }{result1} } -func (fake *FakeMediaTrack) HasMultipleSpatialLayers() bool { - fake.hasMultipleSpatialLayersMutex.Lock() - ret, specificReturn := fake.hasMultipleSpatialLayersReturnsOnCall[len(fake.hasMultipleSpatialLayersArgsForCall)] - fake.hasMultipleSpatialLayersArgsForCall = append(fake.hasMultipleSpatialLayersArgsForCall, struct { - }{}) - stub := fake.HasMultipleSpatialLayersStub - fakeReturns := fake.hasMultipleSpatialLayersReturns - fake.recordInvocation("HasMultipleSpatialLayers", []interface{}{}) - fake.hasMultipleSpatialLayersMutex.Unlock() - if stub != nil { - return stub() - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeMediaTrack) HasMultipleSpatialLayersCallCount() int { - fake.hasMultipleSpatialLayersMutex.RLock() - defer fake.hasMultipleSpatialLayersMutex.RUnlock() - return len(fake.hasMultipleSpatialLayersArgsForCall) -} - -func (fake *FakeMediaTrack) HasMultipleSpatialLayersCalls(stub func() bool) { - fake.hasMultipleSpatialLayersMutex.Lock() - defer fake.hasMultipleSpatialLayersMutex.Unlock() - fake.HasMultipleSpatialLayersStub = stub -} - -func (fake *FakeMediaTrack) HasMultipleSpatialLayersReturns(result1 bool) { - fake.hasMultipleSpatialLayersMutex.Lock() - defer fake.hasMultipleSpatialLayersMutex.Unlock() - fake.HasMultipleSpatialLayersStub = nil - fake.hasMultipleSpatialLayersReturns = struct { - result1 bool - }{result1} -} - -func (fake *FakeMediaTrack) HasMultipleSpatialLayersReturnsOnCall(i int, result1 bool) { - fake.hasMultipleSpatialLayersMutex.Lock() - defer fake.hasMultipleSpatialLayersMutex.Unlock() - fake.HasMultipleSpatialLayersStub = nil - if fake.hasMultipleSpatialLayersReturnsOnCall == nil { - fake.hasMultipleSpatialLayersReturnsOnCall = make(map[int]struct { - result1 bool - }) - } - fake.hasMultipleSpatialLayersReturnsOnCall[i] = struct { - result1 bool - }{result1} -} - func (fake *FakeMediaTrack) ID() livekit.TrackID { fake.iDMutex.Lock() ret, specificReturn := fake.iDReturnsOnCall[len(fake.iDArgsForCall)] @@ -1877,8 +1814,6 @@ func (fake *FakeMediaTrack) Invocations() map[string][][]interface{} { defer fake.getQualityForDimensionMutex.RUnlock() fake.getTemporalLayerForSpatialFpsMutex.RLock() defer fake.getTemporalLayerForSpatialFpsMutex.RUnlock() - fake.hasMultipleSpatialLayersMutex.RLock() - defer fake.hasMultipleSpatialLayersMutex.RUnlock() fake.iDMutex.RLock() defer fake.iDMutex.RUnlock() fake.isEncryptedMutex.RLock() diff --git a/pkg/rtc/wrappedreceiver.go b/pkg/rtc/wrappedreceiver.go index 221975dd1..a4d41a715 100644 --- a/pkg/rtc/wrappedreceiver.go +++ b/pkg/rtc/wrappedreceiver.go @@ -391,14 +391,6 @@ func (d *DummyReceiver) UpdateTrackInfo(ti *livekit.TrackInfo) { } } -func (d *DummyReceiver) IsSimulcast() bool { - if r, ok := d.receiver.Load().(sfu.TrackReceiver); ok { - return r.IsSimulcast() - } - - return false -} - func (d *DummyReceiver) IsClosed() bool { if r, ok := d.receiver.Load().(sfu.TrackReceiver); ok { return r.IsClosed() diff --git a/pkg/service/servicefakes/fake_sipstore.go b/pkg/service/servicefakes/fake_sipstore.go index bc914444c..055018fe0 100644 --- a/pkg/service/servicefakes/fake_sipstore.go +++ b/pkg/service/servicefakes/fake_sipstore.go @@ -146,6 +146,34 @@ type FakeSIPStore struct { result1 *livekit.SIPTrunkInfo result2 error } + SelectSIPDispatchRuleStub func(context.Context, string) ([]*livekit.SIPDispatchRuleInfo, error) + selectSIPDispatchRuleMutex sync.RWMutex + selectSIPDispatchRuleArgsForCall []struct { + arg1 context.Context + arg2 string + } + selectSIPDispatchRuleReturns struct { + result1 []*livekit.SIPDispatchRuleInfo + result2 error + } + selectSIPDispatchRuleReturnsOnCall map[int]struct { + result1 []*livekit.SIPDispatchRuleInfo + result2 error + } + SelectSIPInboundTrunkStub func(context.Context, string) ([]*livekit.SIPInboundTrunkInfo, error) + selectSIPInboundTrunkMutex sync.RWMutex + selectSIPInboundTrunkArgsForCall []struct { + arg1 context.Context + arg2 string + } + selectSIPInboundTrunkReturns struct { + result1 []*livekit.SIPInboundTrunkInfo + result2 error + } + selectSIPInboundTrunkReturnsOnCall map[int]struct { + result1 []*livekit.SIPInboundTrunkInfo + result2 error + } StoreSIPDispatchRuleStub func(context.Context, *livekit.SIPDispatchRuleInfo) error storeSIPDispatchRuleMutex sync.RWMutex storeSIPDispatchRuleArgsForCall []struct { @@ -842,6 +870,136 @@ func (fake *FakeSIPStore) LoadSIPTrunkReturnsOnCall(i int, result1 *livekit.SIPT }{result1, result2} } +func (fake *FakeSIPStore) SelectSIPDispatchRule(arg1 context.Context, arg2 string) ([]*livekit.SIPDispatchRuleInfo, error) { + fake.selectSIPDispatchRuleMutex.Lock() + ret, specificReturn := fake.selectSIPDispatchRuleReturnsOnCall[len(fake.selectSIPDispatchRuleArgsForCall)] + fake.selectSIPDispatchRuleArgsForCall = append(fake.selectSIPDispatchRuleArgsForCall, struct { + arg1 context.Context + arg2 string + }{arg1, arg2}) + stub := fake.SelectSIPDispatchRuleStub + fakeReturns := fake.selectSIPDispatchRuleReturns + fake.recordInvocation("SelectSIPDispatchRule", []interface{}{arg1, arg2}) + fake.selectSIPDispatchRuleMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeSIPStore) SelectSIPDispatchRuleCallCount() int { + fake.selectSIPDispatchRuleMutex.RLock() + defer fake.selectSIPDispatchRuleMutex.RUnlock() + return len(fake.selectSIPDispatchRuleArgsForCall) +} + +func (fake *FakeSIPStore) SelectSIPDispatchRuleCalls(stub func(context.Context, string) ([]*livekit.SIPDispatchRuleInfo, error)) { + fake.selectSIPDispatchRuleMutex.Lock() + defer fake.selectSIPDispatchRuleMutex.Unlock() + fake.SelectSIPDispatchRuleStub = stub +} + +func (fake *FakeSIPStore) SelectSIPDispatchRuleArgsForCall(i int) (context.Context, string) { + fake.selectSIPDispatchRuleMutex.RLock() + defer fake.selectSIPDispatchRuleMutex.RUnlock() + argsForCall := fake.selectSIPDispatchRuleArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeSIPStore) SelectSIPDispatchRuleReturns(result1 []*livekit.SIPDispatchRuleInfo, result2 error) { + fake.selectSIPDispatchRuleMutex.Lock() + defer fake.selectSIPDispatchRuleMutex.Unlock() + fake.SelectSIPDispatchRuleStub = nil + fake.selectSIPDispatchRuleReturns = struct { + result1 []*livekit.SIPDispatchRuleInfo + result2 error + }{result1, result2} +} + +func (fake *FakeSIPStore) SelectSIPDispatchRuleReturnsOnCall(i int, result1 []*livekit.SIPDispatchRuleInfo, result2 error) { + fake.selectSIPDispatchRuleMutex.Lock() + defer fake.selectSIPDispatchRuleMutex.Unlock() + fake.SelectSIPDispatchRuleStub = nil + if fake.selectSIPDispatchRuleReturnsOnCall == nil { + fake.selectSIPDispatchRuleReturnsOnCall = make(map[int]struct { + result1 []*livekit.SIPDispatchRuleInfo + result2 error + }) + } + fake.selectSIPDispatchRuleReturnsOnCall[i] = struct { + result1 []*livekit.SIPDispatchRuleInfo + result2 error + }{result1, result2} +} + +func (fake *FakeSIPStore) SelectSIPInboundTrunk(arg1 context.Context, arg2 string) ([]*livekit.SIPInboundTrunkInfo, error) { + fake.selectSIPInboundTrunkMutex.Lock() + ret, specificReturn := fake.selectSIPInboundTrunkReturnsOnCall[len(fake.selectSIPInboundTrunkArgsForCall)] + fake.selectSIPInboundTrunkArgsForCall = append(fake.selectSIPInboundTrunkArgsForCall, struct { + arg1 context.Context + arg2 string + }{arg1, arg2}) + stub := fake.SelectSIPInboundTrunkStub + fakeReturns := fake.selectSIPInboundTrunkReturns + fake.recordInvocation("SelectSIPInboundTrunk", []interface{}{arg1, arg2}) + fake.selectSIPInboundTrunkMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeSIPStore) SelectSIPInboundTrunkCallCount() int { + fake.selectSIPInboundTrunkMutex.RLock() + defer fake.selectSIPInboundTrunkMutex.RUnlock() + return len(fake.selectSIPInboundTrunkArgsForCall) +} + +func (fake *FakeSIPStore) SelectSIPInboundTrunkCalls(stub func(context.Context, string) ([]*livekit.SIPInboundTrunkInfo, error)) { + fake.selectSIPInboundTrunkMutex.Lock() + defer fake.selectSIPInboundTrunkMutex.Unlock() + fake.SelectSIPInboundTrunkStub = stub +} + +func (fake *FakeSIPStore) SelectSIPInboundTrunkArgsForCall(i int) (context.Context, string) { + fake.selectSIPInboundTrunkMutex.RLock() + defer fake.selectSIPInboundTrunkMutex.RUnlock() + argsForCall := fake.selectSIPInboundTrunkArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeSIPStore) SelectSIPInboundTrunkReturns(result1 []*livekit.SIPInboundTrunkInfo, result2 error) { + fake.selectSIPInboundTrunkMutex.Lock() + defer fake.selectSIPInboundTrunkMutex.Unlock() + fake.SelectSIPInboundTrunkStub = nil + fake.selectSIPInboundTrunkReturns = struct { + result1 []*livekit.SIPInboundTrunkInfo + result2 error + }{result1, result2} +} + +func (fake *FakeSIPStore) SelectSIPInboundTrunkReturnsOnCall(i int, result1 []*livekit.SIPInboundTrunkInfo, result2 error) { + fake.selectSIPInboundTrunkMutex.Lock() + defer fake.selectSIPInboundTrunkMutex.Unlock() + fake.SelectSIPInboundTrunkStub = nil + if fake.selectSIPInboundTrunkReturnsOnCall == nil { + fake.selectSIPInboundTrunkReturnsOnCall = make(map[int]struct { + result1 []*livekit.SIPInboundTrunkInfo + result2 error + }) + } + fake.selectSIPInboundTrunkReturnsOnCall[i] = struct { + result1 []*livekit.SIPInboundTrunkInfo + result2 error + }{result1, result2} +} + func (fake *FakeSIPStore) StoreSIPDispatchRule(arg1 context.Context, arg2 *livekit.SIPDispatchRuleInfo) error { fake.storeSIPDispatchRuleMutex.Lock() ret, specificReturn := fake.storeSIPDispatchRuleReturnsOnCall[len(fake.storeSIPDispatchRuleArgsForCall)] @@ -1113,6 +1271,10 @@ func (fake *FakeSIPStore) Invocations() map[string][][]interface{} { defer fake.loadSIPOutboundTrunkMutex.RUnlock() fake.loadSIPTrunkMutex.RLock() defer fake.loadSIPTrunkMutex.RUnlock() + fake.selectSIPDispatchRuleMutex.RLock() + defer fake.selectSIPDispatchRuleMutex.RUnlock() + fake.selectSIPInboundTrunkMutex.RLock() + defer fake.selectSIPInboundTrunkMutex.RUnlock() fake.storeSIPDispatchRuleMutex.RLock() defer fake.storeSIPDispatchRuleMutex.RUnlock() fake.storeSIPInboundTrunkMutex.RLock() diff --git a/pkg/sfu/downtrack.go b/pkg/sfu/downtrack.go index 1cba43b23..d2472db61 100644 --- a/pkg/sfu/downtrack.go +++ b/pkg/sfu/downtrack.go @@ -586,8 +586,7 @@ func (d *DownTrack) Bind(t webrtc.TrackLocalContext) (webrtc.RTPCodecParameters, d.setBindStateLocked(bindStateBound) d.bindLock.Unlock() - receiver := d.Receiver() - d.forwarder.DetermineCodec(codec.RTPCodecCapability, receiver.HeaderExtensions(), receiver.IsSimulcast()) + d.forwarder.DetermineCodec(codec.RTPCodecCapability, d.Receiver().HeaderExtensions()) d.connectionStats.Start(d.Mime(), isFECEnabled) d.params.Logger.Debugw("downtrack bound") } @@ -696,8 +695,7 @@ func (d *DownTrack) handleUpstreamCodecChange(mimeType string) { ) d.forwarder.Restart() - receiver := d.Receiver() - d.forwarder.DetermineCodec(codec.RTPCodecCapability, receiver.HeaderExtensions(), receiver.IsSimulcast()) + d.forwarder.DetermineCodec(codec.RTPCodecCapability, d.Receiver().HeaderExtensions()) d.connectionStats.UpdateCodec(d.Mime(), isFECEnabled) } diff --git a/pkg/sfu/forwarder.go b/pkg/sfu/forwarder.go index 3d70f10b2..5251e7e90 100644 --- a/pkg/sfu/forwarder.go +++ b/pkg/sfu/forwarder.go @@ -297,11 +297,7 @@ func (f *Forwarder) SetMaxTemporalLayerSeen(maxTemporalLayerSeen int32) bool { return true } -func (f *Forwarder) DetermineCodec( - codec webrtc.RTPCodecCapability, - extensions []webrtc.RTPHeaderExtensionParameter, - isReceiverSimulcast bool, -) { +func (f *Forwarder) DetermineCodec(codec webrtc.RTPCodecCapability, extensions []webrtc.RTPHeaderExtensionParameter) { f.lock.Lock() defer f.lock.Unlock() @@ -344,51 +340,40 @@ func (f *Forwarder) DetermineCodec( } case mime.MimeTypeVP9: - if isReceiverSimulcast { - f.logger.Debugw("selecting simulcast video layer selector for VP9") - if f.vls != nil { - f.vls = videolayerselector.NewSimulcastFromOther(f.vls) - } else { - f.vls = videolayerselector.NewSimulcast(f.logger) - } - // VP9-SIMULCAST-TODO: Add temporal layer selector for VP9 - } else { - isDDAvailable := ddAvailable(extensions) - if isDDAvailable { - f.logger.Debugw("selecting dependency descriptor video layer selector for VP9") - if f.vls != nil { - f.vls = videolayerselector.NewDependencyDescriptorFromOther(f.vls) - } else { - f.vls = videolayerselector.NewDependencyDescriptor(f.logger) - } - } else { - f.logger.Debugw("selecting VP9 SVC video layer selector") - if f.vls != nil { - f.vls = videolayerselector.NewVP9FromOther(f.vls) - } else { - f.vls = videolayerselector.NewVP9(f.logger) - } - } - } - - case mime.MimeTypeAV1: + // DD-TODO : we only enable dd layer selector for av1/vp9 now, in the future we can enable it for vp8 too isDDAvailable := ddAvailable(extensions) - if isReceiverSimulcast || !isDDAvailable { - // AV1-SIMULCAST-TODO: Add temporal layer selector for AV1 - f.logger.Debugw("selecting simulcast video layer selector for AV1") - if f.vls != nil { - f.vls = videolayerselector.NewSimulcastFromOther(f.vls) - } else { - f.vls = videolayerselector.NewSimulcast(f.logger) - } - } else { - f.logger.Debugw("selecting dependency descriptor video layer selector for AV1") + if isDDAvailable { if f.vls != nil { f.vls = videolayerselector.NewDependencyDescriptorFromOther(f.vls) } else { f.vls = videolayerselector.NewDependencyDescriptor(f.logger) } + } else { + if f.vls != nil { + f.vls = videolayerselector.NewVP9FromOther(f.vls) + } else { + f.vls = videolayerselector.NewVP9(f.logger) + } } + // SVC-TODO: Support for VP9 simulcast. When DD is not available, have to pick selector based on VP9 SVC or Simulcast + + case mime.MimeTypeAV1: + // DD-TODO : we only enable dd layer selector for av1/vp9 now, in the future we can enable it for vp8 too + isDDAvailable := ddAvailable(extensions) + if isDDAvailable { + if f.vls != nil { + f.vls = videolayerselector.NewDependencyDescriptorFromOther(f.vls) + } else { + f.vls = videolayerselector.NewDependencyDescriptor(f.logger) + } + } else { + if f.vls != nil { + f.vls = videolayerselector.NewSimulcastFromOther(f.vls) + } else { + f.vls = videolayerselector.NewSimulcast(f.logger) + } + } + // SVC-TODO: Support for AV1 Simulcast } } diff --git a/pkg/sfu/forwarder_test.go b/pkg/sfu/forwarder_test.go index ef7b3e0c2..722c76769 100644 --- a/pkg/sfu/forwarder_test.go +++ b/pkg/sfu/forwarder_test.go @@ -33,7 +33,7 @@ func disable(f *Forwarder) { func newForwarder(codec webrtc.RTPCodecCapability, kind webrtc.RTPCodecType) *Forwarder { f := NewForwarder(kind, logger.GetLogger(), true, nil) - f.DetermineCodec(codec, nil, false) + f.DetermineCodec(codec, nil) return f } diff --git a/pkg/sfu/mime/mimetype.go b/pkg/sfu/mime/mimetype.go index df24ab686..118a7bad8 100644 --- a/pkg/sfu/mime/mimetype.go +++ b/pkg/sfu/mime/mimetype.go @@ -240,6 +240,10 @@ func IsMimeTypeVideo(mimeType MimeType) bool { return strings.HasPrefix(mimeType.String(), MimeTypePrefixVideo) } +// SVC-TODO: Have to use more conditions to differentiate between +// SVC-TODO: SVC and non-SVC (could be single layer or simulcast). +// SVC-TODO: May only need to differentiate between simulcast and non-simulcast +// SVC-TODO: i. e. may be possible to treat single layer as SVC to get proper/intended functionality. func IsMimeTypeSVC(mimeType MimeType) bool { switch mimeType { case MimeTypeAV1, MimeTypeVP9: diff --git a/pkg/sfu/receiver.go b/pkg/sfu/receiver.go index 382e6332a..3f4fd9eff 100644 --- a/pkg/sfu/receiver.go +++ b/pkg/sfu/receiver.go @@ -123,7 +123,6 @@ type TrackReceiver interface { TrackInfo() *livekit.TrackInfo UpdateTrackInfo(ti *livekit.TrackInfo) - IsSimulcast() bool // Get primary receiver if this receiver represents a RED codec; otherwise it will return itself GetPrimaryReceiverForRed() TrackReceiver @@ -266,6 +265,7 @@ func NewWebRTCReceiver( codecState: ReceiverCodecStateNormal, kind: track.Kind(), onRTCP: onRTCP, + isSVC: mime.IsMimeTypeStringSVC(track.Codec().MimeType), isRED: mime.IsMimeTypeStringRED(track.Codec().MimeType), } @@ -274,12 +274,6 @@ func NewWebRTCReceiver( } w.trackInfo.Store(utils.CloneProto(trackInfo)) - isSVC := false - if !w.IsSimulcast() { - isSVC = mime.IsMimeTypeStringSVC(track.Codec().MimeType) - } - w.isSVC = isSVC - w.downTrackSpreader = NewDownTrackSpreader(DownTrackSpreaderParams{ Threshold: w.lbThreshold, Logger: logger, @@ -324,16 +318,6 @@ func (w *WebRTCReceiver) UpdateTrackInfo(ti *livekit.TrackInfo) { w.streamTrackerManager.UpdateTrackInfo(ti) } -func (w *WebRTCReceiver) IsSimulcast() bool { - for _, codec := range w.trackInfo.Load().Codecs { - if mime.IsMimeTypeStringEqual(codec.MimeType, w.codec.MimeType) { - return codec.IsSimulcast - } - } - - return false -} - func (w *WebRTCReceiver) OnStatsUpdate(fn func(w *WebRTCReceiver, stat *livekit.AnalyticsStat)) { w.onStatsUpdate = fn } @@ -871,9 +855,13 @@ func (w *WebRTCReceiver) closeTracks() { } func (w *WebRTCReceiver) DebugInfo() map[string]interface{} { + isSimulcast := !w.isSVC + if ti := w.trackInfo.Load(); ti != nil { + isSimulcast = isSimulcast && len(ti.Layers) > 1 + } info := map[string]interface{}{ "SVC": w.isSVC, - "Simulcast": w.IsSimulcast(), + "Simulcast": isSimulcast, } w.bufferMu.RLock()