mirror of
https://github.com/livekit/livekit.git
synced 2026-10-23 10:52:46 +00:00
shorten the time cost for subscriber get media tracks (#747)
* set DownTrack's initial codec to first codec of potential codecs * faststart on subscribe
This commit is contained in:
1 parent
46301d7d6f
commit
6ba034feae
12 files changed
+97
-32
No files matched your search
@@ -245,7 +245,7 @@ func (t *MediaTrackSubscriptions) AddSubscriber(sub types.LocalParticipant, wr *
|
||||
// since sub will lock, run it in a goroutine to avoid deadlocks
|
||||
go func() {
|
||||
sub.AddSubscribedTrack(subTrack)
|
||||
sub.Negotiate()
|
||||
sub.Negotiate(false)
|
||||
}()
|
||||
|
||||
t.params.Telemetry.TrackSubscribed(context.Background(), subscriberID, t.params.MediaTrack.ToProto(),
|
||||
@@ -708,5 +708,5 @@ func (t *MediaTrackSubscriptions) downTrackClosed(
|
||||
}
|
||||
|
||||
sub.RemoveSubscribedTrack(subTrack)
|
||||
sub.Negotiate()
|
||||
sub.Negotiate(false)
|
||||
}
|
||||
+23
-3
@@ -134,7 +134,8 @@ type ParticipantImpl struct {
|
||||
onClose func(types.LocalParticipant, map[livekit.TrackID]livekit.ParticipantID)
|
||||
onClaimsChanged func(participant types.LocalParticipant)
|
||||
|
||||
activeCounter atomic.Int32
|
||||
activeCounter atomic.Int32
|
||||
firstConnected atomic.Bool
|
||||
}
|
||||
|
||||
func NewParticipant(params ParticipantParams) (*ParticipantImpl, error) {
|
||||
@@ -672,9 +673,11 @@ func (p *ParticipantImpl) Close(sendLeave bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ParticipantImpl) Negotiate() {
|
||||
// Negotiate subscriber SDP with client, if force is true, will cencel pending
|
||||
// negotiate task and negotiate immediately
|
||||
func (p *ParticipantImpl) Negotiate(force bool) {
|
||||
if p.MigrateState() != types.MigrateStateInit {
|
||||
p.subscriber.Negotiate()
|
||||
p.subscriber.Negotiate(force)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -857,6 +860,9 @@ func (p *ParticipantImpl) AddSubscribedTrack(subTrack types.SubscribedTrack) {
|
||||
p.lock.Unlock()
|
||||
|
||||
subTrack.OnBind(func() {
|
||||
if p.firstConnected.Load() {
|
||||
subTrack.DownTrack().SetConnected()
|
||||
}
|
||||
p.subscriber.AddTrack(subTrack)
|
||||
})
|
||||
|
||||
@@ -1114,6 +1120,9 @@ func (p *ParticipantImpl) handleDataMessage(kind livekit.DataPacket_Kind, data [
|
||||
|
||||
func (p *ParticipantImpl) handlePrimaryStateChange(state webrtc.PeerConnectionState) {
|
||||
if state == webrtc.PeerConnectionStateConnected {
|
||||
if !p.firstConnected.Swap(true) {
|
||||
p.setDowntracksConnected()
|
||||
}
|
||||
prometheus.ServiceOperationCounter.WithLabelValues("ice_connection", "success", "").Add(1)
|
||||
if !p.hasPendingMigratedTrack() && p.MigrateState() == types.MigrateStateSync {
|
||||
p.SetMigrateState(types.MigrateStateComplete)
|
||||
@@ -1798,3 +1807,14 @@ func (p *ParticipantImpl) postRtcp(pkts []rtcp.Packet) {
|
||||
p.params.Logger.Warnw("rtcp channel full", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ParticipantImpl) setDowntracksConnected() {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
for _, t := range p.subscribedTracks {
|
||||
if dt := t.DownTrack(); dt != nil {
|
||||
dt.SetConnected()
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-2
@@ -307,7 +307,14 @@ func (r *Room) Join(participant types.LocalParticipant, opts *ParticipantOptions
|
||||
|
||||
if participant.SubscriberAsPrimary() {
|
||||
// initiates sub connection as primary
|
||||
participant.Negotiate()
|
||||
if participant.ProtocolVersion().SupportFastStart() {
|
||||
go func() {
|
||||
r.subscribeToExistingTracks(participant)
|
||||
participant.Negotiate(true)
|
||||
}()
|
||||
} else {
|
||||
participant.Negotiate(true)
|
||||
}
|
||||
}
|
||||
|
||||
prometheus.ServiceOperationCounter.WithLabelValues("participant_join", "success", "").Add(1)
|
||||
@@ -462,7 +469,7 @@ func (r *Room) SetParticipantPermission(participant types.LocalParticipant, perm
|
||||
if r.subscribeToExistingTracks(participant) == 0 {
|
||||
// start negotiating even if there are other media tracks to subscribe
|
||||
// we'll need to set the participant up to receive data
|
||||
participant.Negotiate()
|
||||
participant.Negotiate(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -288,12 +288,21 @@ func (t *PCTransport) OnOffer(f func(sd webrtc.SessionDescription)) {
|
||||
t.onOffer = f
|
||||
}
|
||||
|
||||
func (t *PCTransport) Negotiate() {
|
||||
t.debouncedNegotiate(func() {
|
||||
func (t *PCTransport) Negotiate(force bool) {
|
||||
if force {
|
||||
t.debouncedNegotiate(func() {
|
||||
// no op to cancel pending negotiation
|
||||
})
|
||||
if err := t.CreateAndSendOffer(nil); err != nil {
|
||||
t.logger.Errorw("could not negotiate", err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
t.debouncedNegotiate(func() {
|
||||
if err := t.CreateAndSendOffer(nil); err != nil {
|
||||
t.logger.Errorw("could not negotiate", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (t *PCTransport) CreateAndSendOffer(options *webrtc.OfferOptions) error {
|
||||
|
||||
@@ -126,7 +126,7 @@ type LocalParticipant interface {
|
||||
SubscriberMediaEngine() *webrtc.MediaEngine
|
||||
SubscriberPC() *webrtc.PeerConnection
|
||||
HandleAnswer(sdp webrtc.SessionDescription) error
|
||||
Negotiate()
|
||||
Negotiate(force bool)
|
||||
ICERestart() error
|
||||
AddSubscribedTrack(st SubscribedTrack)
|
||||
RemoveSubscribedTrack(st SubscribedTrack)
|
||||
|
||||
@@ -47,3 +47,9 @@ func (v ProtocolVersion) SupportsICELite() bool {
|
||||
func (v ProtocolVersion) SupportsUnpublish() bool {
|
||||
return v > 6
|
||||
}
|
||||
|
||||
// SupportFastStart - if client supports fast start, server side will send media streams
|
||||
// in the first offer
|
||||
func (v ProtocolVersion) SupportFastStart() bool {
|
||||
return v > 7
|
||||
}
|
||||
@@ -308,9 +308,10 @@ type FakeLocalParticipant struct {
|
||||
migrateStateReturnsOnCall map[int]struct {
|
||||
result1 types.MigrateState
|
||||
}
|
||||
NegotiateStub func()
|
||||
NegotiateStub func(bool)
|
||||
negotiateMutex sync.RWMutex
|
||||
negotiateArgsForCall []struct {
|
||||
arg1 bool
|
||||
}
|
||||
OnClaimsChangedStub func(func(types.LocalParticipant))
|
||||
onClaimsChangedMutex sync.RWMutex
|
||||
@@ -2190,15 +2191,16 @@ func (fake *FakeLocalParticipant) MigrateStateReturnsOnCall(i int, result1 types
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) Negotiate() {
|
||||
func (fake *FakeLocalParticipant) Negotiate(arg1 bool) {
|
||||
fake.negotiateMutex.Lock()
|
||||
fake.negotiateArgsForCall = append(fake.negotiateArgsForCall, struct {
|
||||
}{})
|
||||
arg1 bool
|
||||
}{arg1})
|
||||
stub := fake.NegotiateStub
|
||||
fake.recordInvocation("Negotiate", []interface{}{})
|
||||
fake.recordInvocation("Negotiate", []interface{}{arg1})
|
||||
fake.negotiateMutex.Unlock()
|
||||
if stub != nil {
|
||||
fake.NegotiateStub()
|
||||
fake.NegotiateStub(arg1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2208,12 +2210,19 @@ func (fake *FakeLocalParticipant) NegotiateCallCount() int {
|
||||
return len(fake.negotiateArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) NegotiateCalls(stub func()) {
|
||||
func (fake *FakeLocalParticipant) NegotiateCalls(stub func(bool)) {
|
||||
fake.negotiateMutex.Lock()
|
||||
defer fake.negotiateMutex.Unlock()
|
||||
fake.NegotiateStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) NegotiateArgsForCall(i int) bool {
|
||||
fake.negotiateMutex.RLock()
|
||||
defer fake.negotiateMutex.RUnlock()
|
||||
argsForCall := fake.negotiateArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) OnClaimsChanged(arg1 func(types.LocalParticipant)) {
|
||||
fake.onClaimsChangedMutex.Lock()
|
||||
fake.onClaimsChangedArgsForCall = append(fake.onClaimsChangedArgsForCall, struct {
|
||||
|
||||
Reference in new issue
Block a user