-
Notifications
You must be signed in to change notification settings - Fork 255
fix: improve processor handling #859
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
base: main
Are you sure you want to change the base?
Changes from all commits
211bfe9
ff23d72
591eaba
64aba20
7b7c583
d65a15d
19f3d05
4734a3b
e92daaa
1cd7c2a
1b0a286
8d86095
8eb03d9
5d24c85
3a74e8d
526f347
a2b9154
f297b18
5b6bf43
a46e292
b647017
0f20487
76bafa4
ad56f16
53f1c01
0c04eea
5fbcaad
7637399
2124273
f7b7b32
200df67
e06dc6a
04c164c
69fbbfb
d11065f
99f640e
56f4ab9
87e7ffa
f9534fb
cb76fad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -228,8 +228,25 @@ abstract class Track extends DisposableChangeNotifier with EventsEmittable<Track | |
| } | ||
|
|
||
| @internal | ||
| void setProcessedTrack(rtc.MediaStreamTrack track) { | ||
| _originalTrack = _mediaStreamTrack; | ||
| _mediaStreamTrack = track; | ||
| Future<void> setProcessedTrack(rtc.MediaStreamTrack? track) async { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Release notes entry is missing for a user-visible change The pull request changes published SDK behaviour and the signature of a track method but adds no changeset file under Repository ruleAGENTS.md: "Every PR that affects the published package needs a changeset file in Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| if (track != null) { | ||
| // set processed track | ||
| _originalTrack = _mediaStreamTrack; | ||
| _mediaStreamTrack = track; | ||
| if (_originalTrack != null) { | ||
| await _mediaStream.removeTrack(_originalTrack!); | ||
| } | ||
| await _mediaStream.addTrack(track); | ||
| } else if (_originalTrack != null) { | ||
| // reset processed track | ||
| await _mediaStream.removeTrack(_mediaStreamTrack); | ||
| await _mediaStream.addTrack(_originalTrack!); | ||
| _mediaStreamTrack = _originalTrack!; | ||
| _originalTrack = null; | ||
| } | ||
| events.emit(TrackStreamUpdatedEvent( | ||
| track: this, | ||
| stream: _mediaStream, | ||
| )); | ||
|
Comment on lines
+247
to
+250
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Video widgets are told to re-attach to a media stream that was just destroyed Stopping a local track that uses a processor announces a stream update ( Ordering of dispose and the new event
Emitting only when something actually changed (i.e. inside the two branches of Learn moresetProcessedTrack in lib/src/track/track.dart always emits TrackStreamUpdatedEvent, even when neither branch changed anything (e.g. reset requested while _originalTrack is already null). Combined with LocalTrack.stop() disposing mediaStream before calling stopProcessor(), listeners such as VideoTrackRenderer receive an event carrying an already-disposed stream and re-assign it as srcObject. Consider emitting the event only when the track/stream actually changed, and/or calling stopProcessor() before disposing the media stream in LocalTrack.stop(). Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Stopping a camera with an active effect leaves the track pointing at a dead video source
When a local track is stopped, the newly added restore step (
setProcessedTrack(null)at local.dart) silently does nothing because the saved original camera source was already discarded moments earlier, so the track keeps referring to the destroyed processed source.Impact: After stopping a track that had a processor, the track still exposes the dead processed source instead of the real camera source, so anything that inspects or re-uses the track afterwards sees an unusable source.
Why the reset branch never runs during stop()
LocalTrack.stop()(local.dart) first callssuper.stop(), andTrack.stop()(track.dart) stops_originalTrackand sets it tonullwhile_mediaStreamTrackstill holds the processed track.stopProcessor()then callssetProcessedTrack(null), whose reset branch is guarded byelse if (_originalTrack != null)(track.dart) — already null — so_mediaStreamTrackis never restored. Only the event at track.dart is emitted.A fix would be to restore the original track before/inside
Track.stop()(e.g. call the processor teardown before clearing_originalTrack), or makestop()reset_mediaStreamTrack = _originalTrackwhen it clears it.Learn more
In lib/src/track/track.dart, Track.stop() stops and nulls _originalTrack while _mediaStreamTrack still holds the processor output. The new reset logic added in LocalTrack.stopProcessor() (await setProcessedTrack(null)) is therefore a no-op during stop, leaving _mediaStreamTrack pointing at the destroyed processed track. Consider ordering the processor teardown/restore before Track.stop() clears _originalTrack, or having Track.stop() restore _mediaStreamTrack = _originalTrack when it stops and clears the original.
Was this helpful? React with 👍 or 👎 to provide feedback.