From c4d7fef0cd9d9e8344727bacca672822a5f8d616 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Wed, 15 Sep 2021 12:08:28 -0700 Subject: [PATCH 1/3] Clone and stop local media streams from mediaHandler --- src/webrtc/call.ts | 18 +++++--- src/webrtc/mediaHandler.ts | 95 ++++++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 19 deletions(-) diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 79df07b43..5705c9bb4 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -816,9 +816,7 @@ export class MatrixCall extends EventEmitter { for (const sender of this.screensharingSenders) { this.peerConn.removeTrack(sender); } - for (const track of this.localScreensharingStream.getTracks()) { - track.stop(); - } + this.client.getMediaHandler().stopScreensharingStream(this.localScreensharingStream); this.deleteFeedByStream(this.localScreensharingStream); return false; } @@ -866,9 +864,7 @@ export class MatrixCall extends EventEmitter { }); sender.replaceTrack(track); - for (const track of this.localScreensharingStream.getTracks()) { - track.stop(); - } + this.client.getMediaHandler().stopScreensharingStream(this.localScreensharingStream); this.deleteFeedByStream(this.localScreensharingStream); return false; @@ -1751,6 +1747,16 @@ export class MatrixCall extends EventEmitter { logger.debug(`stopAllMedia (stream=${this.localUsermediaStream})`); for (const feed of this.feeds) { + if (feed.isLocal()) { + if (feed.purpose === SDPStreamMetadataPurpose.Usermedia) { + this.client.getMediaHandler().stopUserMediaStream(feed.stream); + continue; + } else if (feed.purpose === SDPStreamMetadataPurpose.Screenshare) { + this.client.getMediaHandler().stopScreensharingStream(feed.stream); + continue; + } + } + for (const track of feed.stream.getTracks()) { track.stop(); } diff --git a/src/webrtc/mediaHandler.ts b/src/webrtc/mediaHandler.ts index b41e39ba8..ddaf2dde4 100644 --- a/src/webrtc/mediaHandler.ts +++ b/src/webrtc/mediaHandler.ts @@ -22,6 +22,8 @@ import { logger } from "../logger"; export class MediaHandler { private audioInput: string; private videoInput: string; + private userMediaStreams: MediaStream[] = []; + private screensharingStreams: MediaStream[] = []; /** * Set an audio input device to use for MatrixCalls @@ -45,26 +47,93 @@ export class MediaHandler { * @returns {MediaStream} based on passed parameters */ public async getUserMediaStream(audio: boolean, video: boolean): Promise { - const constraints = this.getUserMediaContraints(audio, video); - logger.log("Getting user media with constraints", constraints); - return await navigator.mediaDevices.getUserMedia(constraints); + let stream: MediaStream; + + if (this.userMediaStreams.length === 0) { + const constraints = this.getUserMediaContraints(audio, video); + logger.log("Getting user media with constraints", constraints); + stream = await navigator.mediaDevices.getUserMedia(constraints); + } else { + stream = this.userMediaStreams[this.userMediaStreams.length - 1].clone(); + } + + this.userMediaStreams.push(stream); + + return stream; + } + + /** + * Stops all tracks on the provided usermedia stream + */ + public stopUserMediaStream(mediaStream: MediaStream) { + for (const track of mediaStream.getTracks()) { + track.stop(); + } + + const index = this.userMediaStreams.indexOf(mediaStream); + + if (index !== -1) { + this.userMediaStreams.splice(index, 0); + } } /** * @returns {MediaStream} based on passed parameters */ - public async getScreensharingStream(desktopCapturerSourceId: string): Promise { - const screenshareConstraints = this.getScreenshareContraints(desktopCapturerSourceId); - if (!screenshareConstraints) return null; + public async getScreensharingStream(desktopCapturerSourceId: string): Promise { + let stream: MediaStream; - if (desktopCapturerSourceId) { - // We are using Electron - logger.debug("Getting screen stream using getUserMedia()..."); - return await navigator.mediaDevices.getUserMedia(screenshareConstraints); + if (this.screensharingStreams.length === 0) { + const screenshareConstraints = this.getScreenshareContraints(desktopCapturerSourceId); + if (!screenshareConstraints) return null; + + if (desktopCapturerSourceId) { + // We are using Electron + logger.debug("Getting screen stream using getUserMedia()..."); + stream = await navigator.mediaDevices.getUserMedia(screenshareConstraints); + } else { + // We are not using Electron + logger.debug("Getting screen stream using getDisplayMedia()..."); + stream = await navigator.mediaDevices.getDisplayMedia(screenshareConstraints); + } } else { - // We are not using Electron - logger.debug("Getting screen stream using getDisplayMedia()..."); - return await navigator.mediaDevices.getDisplayMedia(screenshareConstraints); + stream = this.screensharingStreams[this.screensharingStreams.length - 1].clone(); + } + + this.screensharingStreams.push(stream); + + return stream; + } + + /** + * Stops all tracks on the provided screensharing stream + */ + public stopScreensharingStream(mediaStream: MediaStream) { + for (const track of mediaStream.getTracks()) { + track.stop(); + } + + const index = this.userMediaStreams.indexOf(mediaStream); + + if (index !== -1) { + this.userMediaStreams.splice(index, 0); + } + } + + /** + * Stops all local media tracks + */ + public stopAllStreams() { + for (const stream of this.userMediaStreams) { + for (const track of stream.getTracks()) { + track.stop(); + } + } + + for (const stream of this.screensharingStreams) { + for (const track of stream.getTracks()) { + track.stop(); + } } } From f3a2bd6b40fe26b8cc3797fd78e4dd23a2c6f346 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Wed, 15 Sep 2021 12:38:12 -0700 Subject: [PATCH 2/3] Clean up stopAllMedia --- src/webrtc/call.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 5705c9bb4..f1af549ca 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -1747,19 +1747,15 @@ export class MatrixCall extends EventEmitter { logger.debug(`stopAllMedia (stream=${this.localUsermediaStream})`); for (const feed of this.feeds) { - if (feed.isLocal()) { - if (feed.purpose === SDPStreamMetadataPurpose.Usermedia) { - this.client.getMediaHandler().stopUserMediaStream(feed.stream); - continue; - } else if (feed.purpose === SDPStreamMetadataPurpose.Screenshare) { - this.client.getMediaHandler().stopScreensharingStream(feed.stream); - continue; + if (feed.isLocal() && feed.purpose === SDPStreamMetadataPurpose.Usermedia) { + this.client.getMediaHandler().stopUserMediaStream(feed.stream); + } else if (feed.isLocal() && feed.purpose === SDPStreamMetadataPurpose.Screenshare) { + this.client.getMediaHandler().stopScreensharingStream(feed.stream); + } else { + for (const track of feed.stream.getTracks()) { + track.stop(); } } - - for (const track of feed.stream.getTracks()) { - track.stop(); - } } } From 422853298cca39926637820d292a7db75963cfed Mon Sep 17 00:00:00 2001 From: Robert Long Date: Wed, 15 Sep 2021 13:20:52 -0700 Subject: [PATCH 3/3] Reset media stream arrays --- src/webrtc/mediaHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/webrtc/mediaHandler.ts b/src/webrtc/mediaHandler.ts index ddaf2dde4..97edf1774 100644 --- a/src/webrtc/mediaHandler.ts +++ b/src/webrtc/mediaHandler.ts @@ -135,6 +135,9 @@ export class MediaHandler { track.stop(); } } + + this.userMediaStreams = []; + this.screensharingStreams = []; } private getUserMediaContraints(audio: boolean, video: boolean): MediaStreamConstraints {