fix: revert recent changes to determine simulcast from sdp (#3565)

* Revert "Audio uses signal SignalCid and SdpCid. (#3564)"

This reverts commit cdfbb106d1.

* Revert "Keep simulcast information tied to receiver. (#3563)"

This reverts commit ed5e2f16b2.

* Revert "chore(logs): log VLS type for VP9/AV1 (#3561)"

This reverts commit ad010cfc43.

* Revert "fix(video): determine svc/simulcast from SDP for advanced codecs (#3549)"

This reverts commit 15f565510c.

* chore(deps): update protocol
This commit is contained in:
Anunay Maheshwari
2025-03-31 23:15:44 +05:30
committed by GitHub
parent cdfbb106d1
commit 52ce18d56e
19 changed files with 312 additions and 486 deletions
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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=
+17 -26
View File
@@ -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())
+5 -37
View File
@@ -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)
+11 -65
View File
@@ -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
}
}
+1 -1
View File
@@ -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
+1 -6
View File
@@ -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
}
+4 -1
View File
@@ -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
+1 -1
View File
@@ -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(),
})
}
+1 -3
View File
@@ -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)
@@ -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()
@@ -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()
-8
View File
@@ -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()
+162
View File
@@ -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()
+2 -4
View File
@@ -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)
}
+28 -43
View File
@@ -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
}
}
+1 -1
View File
@@ -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
}
+4
View File
@@ -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:
+6 -18
View File
@@ -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()