Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

room.LocalParticipant.UnpublishTrack(sid) does not completely unpublish a simulcast track #393

Open
neilyoung opened this issue Jan 31, 2024 · 5 comments

Comments

@neilyoung
Copy link

Details here. There is a significant behavioural difference, if just one track is unpublished or a simulcast track. On the other hand I haven't found any other unpublish function for simulcast

https://livekit-users.slack.com/archives/C01KVTJH6BX/p1706698776125179

@neilyoung
Copy link
Author

@neilyoung
Copy link
Author

Some comments? Solution is available in Slack

@davidzhao
Copy link
Member

this is on our backlog. However, if you'd like to submit a PR for it, we'd welcome it.

@neilyoung
Copy link
Author

Neither my GO nor my deeper understanding of the purpose of the failing code allows me to do that :)

I just know, that this patch works for both, but I guess, it's. not good enough:

	var err error
	//if localTrack, ok := pub.track.(webrtc.TrackLocal); ok {
		for _, sender := range p.engine.publisher.pc.GetSenders() {
			//if sender.Track() == localTrack {
				err = p.engine.publisher.pc.RemoveTrack(sender)
				//break
			//}
		}
		p.engine.publisher.Negotiate()
	//}

Also - VSCode's debugging support is not sufficient to have a full understanding for what happens here, I'm sorry

@patstart
Copy link

  1. The root cause of the issue is that when "LocalParticipant.PublishSimulcastTrack.NewLocalTrackPublication" is called, the main track is not passed, resulting in "UnpublishTrack" not successfully invoking "p.engine.publisher.pc.RemoveTrack".
    pub := NewLocalTrackPublication(KindFromRTPType(mainTrack.Kind()), nil, *opts, p.engine.client)

  2. The minimal change solution is as follows:

        // [origin code in v1.1.2]
	var err error
	if localTrack, ok := pub.track.(webrtc.TrackLocal); ok {
		for _, sender := range p.engine.publisher.pc.GetSenders() {
			if sender.Track() == localTrack {
				err = p.engine.publisher.pc.RemoveTrack(sender)
				break
			}
		}
		p.engine.publisher.Negotiate()
	}



        // [fixed code in v1.1.2]
	var localTracks []webrtc.TrackLocal
	if localTrack, ok := pub.track.(webrtc.TrackLocal); ok {
		localTracks = append(localTracks, localTrack)
	}
	if pub.simulcastTracks != nil {
		for _, track := range pub.simulcastTracks {
			localTracks = append(localTracks, track)
		}
	}

	var err error
	if localTracks != nil && len(localTracks) > 0 {
		for _, localTrack := range localTracks {
			for _, sender := range p.engine.publisher.pc.GetSenders() {
				if sender.Track() == localTrack {
					e := p.engine.publisher.pc.RemoveTrack(sender)
					if e != nil {
						err = e
					}
					break
				}
			}
		}
		p.engine.publisher.Negotiate()
	}
  1. I found that when publishing with simulcast tracks, the trackPublicationBase.track was not set. This not only affects the UnpublishTrack function but may also impact the following logic. However, I have not deeply understood it, so I have not made any changes.
func (r *Room) sendSyncState() {
        ...

	var publishedTracks []*livekit.TrackPublishedResponse
	for _, t := range r.LocalParticipant.Tracks() {
		if t.Track() != nil {
			publishedTracks = append(publishedTracks, &livekit.TrackPublishedResponse{
				Cid:   t.Track().ID(),
				Track: t.TrackInfo(),
			})
		}
	}

        ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants