diff --git a/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js b/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js index 761e383ede9eafae27c72990146aaadfc41a26e2..a31bda83b2bbeb32b7cab0981f4013302d43d696 100755 --- a/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js +++ b/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js @@ -63,14 +63,77 @@ export default class KurentoScreenshareBridge { return normalizedError; } - async kurentoWatchVideo() { + static playElement(screenshareMediaElement) { + const mediaTagPlayed = () => { + logger.info({ + logCode: 'screenshare_media_play_success', + }, 'Screenshare media played successfully'); + }; + + if (screenshareMediaElement.paused) { + // Tag isn't playing yet. Play it. + screenshareMediaElement.play() + .then(mediaTagPlayed) + .catch((error) => { + // NotAllowedError equals autoplay issues, fire autoplay handling event. + // This will be handled in the screenshare react component. + if (error.name === 'NotAllowedError') { + logger.error({ + logCode: 'screenshare_error_autoplay', + extraInfo: { errorName: error.name }, + }, 'Screenshare play failed due to autoplay error'); + const tagFailedEvent = new CustomEvent('screensharePlayFailed', + { detail: { mediaElement: screenshareMediaElement } }); + window.dispatchEvent(tagFailedEvent); + } else { + // Tag failed for reasons other than autoplay. Log the error and + // try playing again a few times until it works or fails for good + const played = playAndRetry(screenshareMediaElement); + if (!played) { + logger.error({ + logCode: 'screenshare_error_media_play_failed', + extraInfo: { errorName: error.name }, + }, `Screenshare media play failed due to ${error.name}`); + } else { + mediaTagPlayed(); + } + } + }); + } else { + // Media tag is already playing, so log a success. This is really a + // logging fallback for a case that shouldn't happen. But if it does + // (ie someone re-enables the autoPlay prop in the element), then it + // means the stream is playing properly and it'll be logged. + mediaTagPlayed(); + } + }; + + static screenshareElementLoadAndPlay(stream, element, muted) { + element.muted = muted; + element.pause(); + element.srcObject = stream; + KurentoScreenshareBridge.playElement(element); + } + + kurentoViewLocalPreview() { + const screenshareMediaElement = document.getElementById(SCREENSHARE_VIDEO_TAG); + const { webRtcPeer } = window.kurentoManager.kurentoScreenshare; + + if (webRtcPeer) { + const stream = webRtcPeer.getLocalStream(); + KurentoScreenshareBridge.screenshareElementLoadAndPlay(stream, screenshareMediaElement, true); + } + } + + async kurentoViewScreen() { + const screenshareMediaElement = document.getElementById(SCREENSHARE_VIDEO_TAG); let iceServers = []; let started = false; try { iceServers = await fetchWebRTCMappedStunTurnServers(getSessionToken()); } catch (error) { - logger.error({ logCode: 'screenshare_viwer_fetchstunturninfo_error', extraInfo: { error } }, + logger.error({ logCode: 'screenshare_viewer', extraInfo: { error } }, 'Screenshare bridge failed to fetch STUN/TURN info, using default'); iceServers = getMappedFallbackStun(); } finally { @@ -139,10 +202,11 @@ export default class KurentoScreenshareBridge { const { webRtcPeer } = window.kurentoManager.kurentoVideo; if (webRtcPeer) { const stream = webRtcPeer.getRemoteStream(); - screenshareTag.muted = true; - screenshareTag.pause(); - screenshareTag.srcObject = stream; - playElement(); + KurentoScreenshareBridge.screenshareElementLoadAndPlay( + stream, + screenshareMediaElement, + true, + ); } }; diff --git a/bigbluebutton-html5/imports/ui/components/screenshare/service.js b/bigbluebutton-html5/imports/ui/components/screenshare/service.js index 51340cba8a3800d399a99b7b618e6fccb54f4a13..b310b8bc203e7edd90cbf10981cddaf25551dbd9 100644 --- a/bigbluebutton-html5/imports/ui/components/screenshare/service.js +++ b/bigbluebutton-html5/imports/ui/components/screenshare/service.js @@ -29,15 +29,21 @@ const presenterScreenshareHasEnded = () => { KurentoBridge.kurentoExitVideo(); }; +const viewScreenshare = () => { + const amIPresenter = UserListService.isUserPresenter(Auth.userID); + if (!amIPresenter) { + KurentoBridge.kurentoViewScreen(amIPresenter); + } else { + KurentoBridge.kurentoViewLocalPreview(); + } +}; + // if remote screenshare has been started connect and display the video stream const presenterScreenshareHasStarted = () => { - // KurentoBridge.kurentoWatchVideo: references a function in the global - // namespace inside kurento-extension.js that we load dynamically - // WebRTC restrictions may need a capture device permission to release // useful ICE candidates on recvonly/no-gUM peers tryGenerateIceCandidates().then(() => { - KurentoBridge.kurentoWatchVideo(); + viewScreenshare(); }).catch((error) => { logger.error({ logCode: 'screenshare_no_valid_candidate_gum_failure', @@ -47,7 +53,7 @@ const presenterScreenshareHasStarted = () => { }, }, `Forced gUM to release additional ICE candidates failed due to ${error.name}.`); // The fallback gUM failed. Try it anyways and hope for the best. - KurentoBridge.kurentoWatchVideo(); + viewScreenshare(); }); };