From 023eee86f494481d3733e00bdf96aca22969af08 Mon Sep 17 00:00:00 2001 From: Thanh Dodeur Date: Sun, 26 Sep 2021 16:19:38 +0000 Subject: [PATCH] [FIX] mail: prevents frozen video elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, when a video track ended unexpectedly, the peers were not notified that the remote track ended, which made it so that inactive video elements remained on screen. This commit fixes this issue. closes odoo/odoo#77875 X-original-commit: d868582b2b409ec01bc4983429dea723f27f5513 Signed-off-by: Sébastien Theys (seb) --- addons/mail/static/src/models/rtc/rtc.js | 40 ++++++++++--------- .../src/models/rtc_session/rtc_session.js | 8 +--- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/addons/mail/static/src/models/rtc/rtc.js b/addons/mail/static/src/models/rtc/rtc.js index 0c5ca824fae..e9167f56d7d 100644 --- a/addons/mail/static/src/models/rtc/rtc.js +++ b/addons/mail/static/src/models/rtc/rtc.js @@ -652,7 +652,14 @@ function factory(dependencies) { }); } if (type === 'video' && isSendingVideo === false) { - rtcSession.removeVideo({ stopTracks: false }); + /** + * Since WebRTC "unified plan", the local track is tied to the + * remote transceiver.sender and not the remote track. Therefore + * when the remote track is 'ended' the local track is not 'ended' + * but only 'muted'. This is why we do not stop the local track + * until the peer is completely removed. + */ + rtcSession.update({ videoStream: clear() }); } } @@ -905,23 +912,9 @@ function factory(dependencies) { for (const [token, peerConnection] of Object.entries(this._peerConnections)) { await this._updateRemoteTrack(peerConnection, 'video', { token }); } - const isScreenSharingOn = !!this.sendDisplay; - const isCameraOn = !!this.sendUserVideo; this.currentRtcSession.updateAndBroadcast({ - isScreenSharingOn, - isCameraOn, - }); - if (isScreenSharingOn || isCameraOn) { - // the peer already gets notified through RTC transaction. - return; - } - this._notifyPeers(Object.keys(this._peerConnections), { - event: 'trackChange', - type: 'peerToPeer', - payload: { - type: 'video', - state: { isSendingVideo: false }, - }, + isScreenSharingOn: !!this.sendDisplay, + isCameraOn: !!this.sendUserVideo, }); } @@ -973,7 +966,6 @@ function factory(dependencies) { }); } if (track.kind === 'video') { - rtcSession.removeVideo({ stopTracks: false }); rtcSession.update({ videoStream: stream, }); @@ -1049,7 +1041,7 @@ function factory(dependencies) { if (videoTrack) { videoTrack.addEventListener('ended', async () => { await this.async(() => - this._toggleLocalVideoTrack({ force: false, type }) + this._toggleVideoBroadcast({ force: false, type }) ); }); } @@ -1105,6 +1097,16 @@ function factory(dependencies) { } catch (e) { // ignored, the transceiver is probably already removed } + if (trackKind === 'video') { + this._notifyPeers([token], { + event: 'trackChange', + type: 'peerToPeer', + payload: { + type: 'video', + state: { isSendingVideo: false }, + }, + }); + } } //---------------------------------------------------------------------- diff --git a/addons/mail/static/src/models/rtc_session/rtc_session.js b/addons/mail/static/src/models/rtc_session/rtc_session.js index 2a0e846059a..81d9cdca8a4 100644 --- a/addons/mail/static/src/models/rtc_session/rtc_session.js +++ b/addons/mail/static/src/models/rtc_session/rtc_session.js @@ -46,13 +46,9 @@ function factory(dependencies) { /** * cleanly removes the video stream of the session - * - * @param {Object} [param0] - * @param {Object} [param0.stopTracks] true if tracks have to be stopped, - * it is optional as tracks can be removed but still necessary for transceivers. */ - removeVideo({ stopTracks = true } = {}) { - if (this.videoStream && stopTracks) { + removeVideo() { + if (this.videoStream) { for (const track of this.videoStream.getTracks() || []) { track.stop(); }