import { getServerConfig, getRTCConfiguration } from "../../js/config.js";
import { createDisplayStringArray } from "../../js/stats.js";
import { VideoPlayer } from "../../js/videoplayer.js";
import { RenderStreaming } from "../../module/renderstreaming.js";
import { Signaling, WebSocketSignaling } from "../../module/signaling.js";
/** @type {Element} */
let playButton;
/** @type {RenderStreaming} */
let renderstreaming;
/** @type {boolean} */
let useWebSocket;
const codecPreferences = document.getElementById('codecPreferences');
const supportsSetCodecPreferences = window.RTCRtpTransceiver &&
'setCodecPreferences' in window.RTCRtpTransceiver.prototype;
const messageDiv = document.getElementById('message');
messageDiv.style.display = 'none';
const playerDiv = document.getElementById('player');
const lockMouseCheck = document.getElementById('lockMouseCheck');
const videoPlayer = new VideoPlayer();
setup();
window.document.oncontextmenu = function () {
return false; // cancel default menu
};
window.addEventListener('resize', function () {
videoPlayer.resizeVideo();
}, true);
window.addEventListener('beforeunload', async () => {
if(!renderstreaming)
return;
await renderstreaming.stop();
}, true);
async function setup() {
const res = await getServerConfig();
useWebSocket = res.useWebSocket;
showWarningIfNeeded(res.startupMode);
showCodecSelect();
showPlayButton();
}
function showWarningIfNeeded(startupMode) {
const warningDiv = document.getElementById("warning");
if (startupMode == "private") {
warningDiv.innerHTML = "
Warning
This sample is not working on Private Mode.";
warningDiv.hidden = false;
}
}
function showPlayButton() {
if (!document.getElementById('playButton')) {
const elementPlayButton = document.createElement('img');
elementPlayButton.id = 'playButton';
elementPlayButton.src = '../../images/Play.png';
elementPlayButton.alt = 'Start Streaming';
playButton = document.getElementById('player').appendChild(elementPlayButton);
playButton.addEventListener('click', onClickPlayButton);
}
}
function onClickPlayButton() {
playButton.style.display = 'none';
// add video player
videoPlayer.createPlayer(playerDiv, lockMouseCheck);
setupRenderStreaming();
}
async function setupRenderStreaming() {
codecPreferences.disabled = true;
const signaling = useWebSocket ? new WebSocketSignaling() : new Signaling();
const config = getRTCConfiguration();
renderstreaming = new RenderStreaming(signaling, config);
renderstreaming.onConnect = onConnect;
renderstreaming.onDisconnect = onDisconnect;
renderstreaming.onTrackEvent = (data) => videoPlayer.addTrack(data.track);
renderstreaming.onGotOffer = setCodecPreferences;
await renderstreaming.start();
await renderstreaming.createConnection();
}
function onConnect() {
const channel = renderstreaming.createDataChannel("input");
videoPlayer.setupInput(channel);
showStatsMessage();
}
async function onDisconnect(connectionId) {
clearStatsMessage();
messageDiv.style.display = 'block';
messageDiv.innerText = `Disconnect peer on ${connectionId}.`;
await renderstreaming.stop();
renderstreaming = null;
videoPlayer.deletePlayer();
if (supportsSetCodecPreferences) {
codecPreferences.disabled = false;
}
showPlayButton();
}
function setCodecPreferences() {
/** @type {RTCRtpCodecCapability[] | null} */
let selectedCodecs = null;
if (supportsSetCodecPreferences) {
const preferredCodec = codecPreferences.options[codecPreferences.selectedIndex];
if (preferredCodec.value !== '') {
const [mimeType, sdpFmtpLine] = preferredCodec.value.split(' ');
const { codecs } = RTCRtpSender.getCapabilities('video');
const selectedCodecIndex = codecs.findIndex(c => c.mimeType === mimeType && c.sdpFmtpLine === sdpFmtpLine);
const selectCodec = codecs[selectedCodecIndex];
selectedCodecs = [selectCodec];
}
}
if (selectedCodecs == null) {
return;
}
const transceivers = renderstreaming.getTransceivers().filter(t => t.receiver.track.kind == "video");
if (transceivers && transceivers.length > 0) {
transceivers.forEach(t => t.setCodecPreferences(selectedCodecs));
}
}
function showCodecSelect() {
if (!supportsSetCodecPreferences) {
messageDiv.style.display = 'block';
messageDiv.innerHTML = `Current Browser does not support RTCRtpTransceiver.setCodecPreferences.`;
return;
}
const codecs = RTCRtpSender.getCapabilities('video').codecs;
codecs.forEach(codec => {
if (['video/red', 'video/ulpfec', 'video/rtx'].includes(codec.mimeType)) {
return;
}
const option = document.createElement('option');
option.value = (codec.mimeType + ' ' + (codec.sdpFmtpLine || '')).trim();
option.innerText = option.value;
codecPreferences.appendChild(option);
});
codecPreferences.disabled = false;
}
/** @type {RTCStatsReport} */
let lastStats;
/** @type {number} */
let intervalId;
function showStatsMessage() {
intervalId = setInterval(async () => {
if (renderstreaming == null) {
return;
}
const stats = await renderstreaming.getStats();
if (stats == null) {
return;
}
const array = createDisplayStringArray(stats, lastStats);
if (array.length) {
messageDiv.style.display = 'block';
messageDiv.innerHTML = array.join('
');
}
lastStats = stats;
}, 1000);
}
function clearStatsMessage() {
if (intervalId) {
clearInterval(intervalId);
}
lastStats = null;
intervalId = null;
messageDiv.style.display = 'none';
messageDiv.innerHTML = '';
}