Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorDaniel Calviño Sánchez <danxuliu@gmail.com>2022-03-31 09:08:26 +0300
committerDaniel Calviño Sánchez <danxuliu@gmail.com>2022-03-31 18:09:57 +0300
commit0cc75c5b0973976f6ba1827c085f8d43d91b6b59 (patch)
tree08b832164911ef73d347c5eaccf5e6bb0ff0a0ea /src/utils
parenta7a9e8368a7ac5795a46ab873a55206998dd3c6a (diff)
Fix reconnections on single media permission changes
Until now the audio and video publishing permissions were handled as a whole; either the local participant was able to publish both audio and video or not. However, the permissions API is actually finer grained, and it is possible to have one without the other. Now the allowed state of local media is updated based on the publishing permissions, which automatically starts and stops the tracks as needed. Nevertheless, in some cases forced reconnections need to be explicitly triggered to remove tracks from the senders, as well as to start and stop the local media. Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/webrtc/webrtc.js85
1 files changed, 75 insertions, 10 deletions
diff --git a/src/utils/webrtc/webrtc.js b/src/utils/webrtc/webrtc.js
index bf56c57f6..babd0b519 100644
--- a/src/utils/webrtc/webrtc.js
+++ b/src/utils/webrtc/webrtc.js
@@ -982,20 +982,41 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
return
}
- if ((currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)
- && (currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO)
- && webrtc.webrtc.isLocalMediaActive()) {
+ if (webrtc.webrtc.isAudioAllowed() === !!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)
+ && webrtc.webrtc.isVideoAllowed() === !!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO)) {
return
}
- if (!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)
- && !(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO)
- && !webrtc.webrtc.isLocalMediaActive()) {
- return
+ let hasAudioSenders = false
+ let hasVideoSenders = false
+
+ webrtc.webrtc.getPeers(null, 'video').forEach(peer => {
+ // Look for any sender of each kind, even if the sender no longer
+ // has a track attached to it.
+ const audioSender = peer.pc.getSenders().find((sender) => sender.kind === 'audio' || (sender.track && sender.track.kind === 'audio') || (sender.trackDisabled && sender.trackDisabled.kind === 'audio'))
+ const videoSender = peer.pc.getSenders().find((sender) => sender.kind === 'video' || (sender.track && sender.track.kind === 'video') || (sender.trackDisabled && sender.trackDisabled.kind === 'video'))
+
+ hasAudioSenders ||= !!audioSender
+ hasVideoSenders ||= !!videoSender
+ })
+
+ const removeSender = (hasAudioSenders && !(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO))
+ || (hasVideoSenders && !(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO))
+
+ if (currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO) {
+ webrtc.webrtc.allowAudio()
+ } else {
+ webrtc.webrtc.disallowAudio()
}
- // FIXME handle case where only one of the permissions is given
- if (!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)
+ if (currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO) {
+ webrtc.webrtc.allowVideo()
+ } else {
+ webrtc.webrtc.disallowVideo()
+ }
+
+ if (webrtc.webrtc.isLocalMediaActive()
+ && !(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)
&& !(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO)) {
startedWithMedia = undefined
@@ -1011,6 +1032,46 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
return
}
+ // If a sender kind is no longer allowed a forced reconnection needs to
+ // be explicitly triggered. Otherwise "removing" the no longer allowed
+ // track will just set it to null in the sender, which does not trigger
+ // a "negotiationneeded" event and thus an automatic forced
+ // reconnection.
+ if (webrtc.webrtc.isLocalMediaActive() && removeSender) {
+ let flags = signaling.getCurrentCallFlags()
+ if (!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)) {
+ flags &= ~PARTICIPANT.CALL_FLAG.WITH_AUDIO
+ }
+ if (!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO)) {
+ flags &= ~PARTICIPANT.CALL_FLAG.WITH_VIDEO
+ }
+
+ // The flags may be updated later if, besides removing a sender, a
+ // track is also added (for example, when there are both a
+ // microphone and a camera and audio permissions are removed at the
+ // same time that video permissions are added). However, at this
+ // point it is not possible to know if that will happen (getting the
+ // new track is an async operation and it could fail), so the flags
+ // are updated only with the known values.
+ forceReconnect(signaling, flags)
+
+ return
+ }
+
+ // If media is already active and a track is added "negotiationneeded"
+ // will be triggered, which in turn will automatically force a
+ // reconnection.
+ if (webrtc.webrtc.isLocalMediaActive()) {
+ return
+ }
+
+ // If media is not active but the participant does not have publishing
+ // permissions there is no need to start the media nor reconnect.
+ if (!(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO)
+ && !(currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO)) {
+ return
+ }
+
const forceReconnectOnceLocalMediaStarted = (constraints) => {
webrtc.off('localMediaStarted', forceReconnectOnceLocalMediaStarted)
webrtc.off('localMediaError', forceReconnectOnceLocalMediaError)
@@ -1045,7 +1106,11 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
startedWithMedia = undefined
- webrtc.startLocalVideo()
+ const constraints = {
+ audio: currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_AUDIO,
+ video: currentParticipant.participantPermissions & PARTICIPANT.PERMISSIONS.PUBLISH_VIDEO,
+ }
+ webrtc.startLocalVideo(constraints)
}
signaling.on('usersInRoom', function(users) {