Turn off the camera when the video is disabled during a call#18788
Open
vladopol wants to merge 2 commits into
Open
Turn off the camera when the video is disabled during a call#18788vladopol wants to merge 2 commits into
vladopol wants to merge 2 commits into
Conversation
The local video and audio control buttons subscribe to the shared device manager to populate the device list, but that also grabbed a live camera stream which was never actually used. As a result the camera (and its hardware light) stayed on for the whole call even when the video was disabled. Let the in-call buttons subscribe without a live video preview, so the camera is only grabbed by components that actually show a preview (the device settings dialog). Partial fix for nextcloud#4008 Signed-off-by: Vladimir Poluliashenko <vladopol@gmail.com>
When the video was disabled during a call the video track was only disabled (track.enabled = false) but kept alive, so Chromium did not release the camera and its hardware light stayed on (Chromium does not honour the "SHOULD release the device" part of the mediacapture spec). Fully stop the camera track when the video is disabled (releasing the camera and turning off its hardware light) and grab it again when the video is enabled, via a new "videoActive" state in MediaDevicesSource that is orthogonal to "videoAllowed" (permissions). Keep "videoAvailable" based on whether a camera input device is selected rather than on the presence of a live track, so the video controls stay usable while the camera is released, including when the call is joined with the video already disabled. Partial fix for nextcloud#4008 Signed-off-by: Vladimir Poluliashenko <vladopol@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4008
Summary
During a call the camera hardware light stayed on even when the video was
disabled (and it kept the camera busy for other applications). This has been
reported for years, both in the browser and, more visibly, in the Talk Desktop
(Electron) client.
Digging into it, the camera was actually held by two independent grabs at
the same time, which is why previous attempts that only addressed one of them
never turned the light off:
The call media pipeline kept the camera track alive and only disabled
it (
track.enabled = false) when the video was turned off. Chromium does nothonour the "SHOULD release the device when all tracks are disabled" part of
the mediacapture spec
(see the corresponding Chromium issue), so the camera β and its light β stays
on. Firefox releases it, Chromium/Electron does not.
The in-call device buttons (
LocalVideoControlButton/LocalAudioControlButton) subscribed to the shared device manager to buildthe device dropdown, which also grabbed a live camera stream that was never
actually used for anything. This kept a second camera track alive for the
whole call, independently of whether the video was enabled.
Selecting "None" as the camera turned the light off precisely because it
released both grabs (the pipeline via the
videoInputIdchange and thedevice buttons via their watcher). This PR fixes both so the light turns off
whenever the video is disabled.
Changes
The PR is split into two independent commits:
1.
fix(call): release the camera used by in-call device buttonsThe in-call control buttons only need the device list, not a live preview, so
they now subscribe to
useDeviceswith{ videoPreview: false }. A live videostream is only grabbed when a subscriber actually shows a preview (the device
settings dialog). This removes the redundant camera grab (#2 above) β it also
means one fewer
getUserMediaper call.2.
fix(call): release the camera when the video is disabledMediaDevicesSourcegets avideoActivestate, orthogonal to the existingvideoAllowed(permissions) state. When the video is disabled the video trackis fully stopped (releasing the camera and turning off its light) instead
of just disabled; when the video is enabled again the camera is grabbed anew.
LocalMedia.pauseVideo()/resumeVideo()drive that state.LocalMediaModelnow derivesvideoAvailablefrom whether a camera inputdevice is selected rather than from the presence of a live track, so the
video controls stay usable while the camera is released β including when the
call is joined with the video already disabled. The model state while the
video is off is otherwise identical to the previous "muted" state
(
videoAvailable: true,videoEnabled: false), so what is broadcast to otherparticipants does not change.
Testing
Manual (Talk Desktop / Electron on macOS, HPB backend, with blur enabled):
β camera comes back immediately.
enables the camera (the light turns on) instead of opening the device dialog,
and disabling it again turns the light back off.
keep working.
Automated:
MediaDevicesSource.setVideoActive()(release on disable,re-grab on enable, gating of
start()and of device changes while inactive,no grab when not allowed).
Notes
the microphone level indicator are all unchanged. Only the redundant, unused
video
getUserMediathe buttons performed in the background is dropped.The audio capture used for the microphone level indicator is left untouched.
getUserMedia); in testing this was immediate.Checklist