From 80207cde0c7fa08be8efe6f9914a3e066e35999b Mon Sep 17 00:00:00 2001 From: youennf Date: Tue, 19 Oct 2021 16:22:00 +0200 Subject: [PATCH] Make use of RTCRtpScriptTransform if available. (#1468) * Make use of RTCRtpScriptTransform if available. Use VP8 by default as it works best with encryption transforms. * fix some style issues * Add RTCRtpScriptTransform as global * Addressing comments * lint Co-authored-by: Harald Alvestrand Co-authored-by: Christoffer Jansson --- .../endtoend-encryption/js/main.js | 36 +++++++++++++------ .../endtoend-encryption/js/videopipe.js | 3 +- .../endtoend-encryption/js/worker.js | 23 +++++++++--- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/content/insertable-streams/endtoend-encryption/js/main.js b/src/content/insertable-streams/endtoend-encryption/js/main.js index a49bb6de3..982c3242a 100644 --- a/src/content/insertable-streams/endtoend-encryption/js/main.js +++ b/src/content/insertable-streams/endtoend-encryption/js/main.js @@ -8,6 +8,7 @@ 'use strict'; +/* global RTCRtpScriptTransform */ /* global VideoPipe */ const video1 = document.querySelector('video#video1'); @@ -38,20 +39,25 @@ let localStream; // eslint-disable-next-line no-unused-vars let remoteStream; -const supportsInsertableStreams = +let hasEnoughAPIs = !!window.RTCRtpScriptTransform; + +if (!hasEnoughAPIs) { + const supportsInsertableStreams = !!RTCRtpSender.prototype.createEncodedStreams; -let supportsTransferableStreams = false; -try { - const stream = new ReadableStream(); - window.postMessage(stream, '*', [stream]); - supportsTransferableStreams = true; -} catch (e) { - console.error('Transferable streams are not supported.'); + let supportsTransferableStreams = false; + try { + const stream = new ReadableStream(); + window.postMessage(stream, '*', [stream]); + supportsTransferableStreams = true; + } catch (e) { + console.error('Transferable streams are not supported.'); + } + hasEnoughAPIs = supportsInsertableStreams && supportsTransferableStreams; } -if (!(supportsInsertableStreams && supportsTransferableStreams)) { - banner.innerText = 'Your browser does not support Insertable Streams. ' + +if (!hasEnoughAPIs) { + banner.innerText = 'Your browser does not support WebRTC Encoded Transforms. ' + 'This sample will not work.'; if (adapter.browserDetails.browser === 'chrome') { banner.innerText += ' Try with Enable experimental Web Platform features enabled from chrome://flags.'; @@ -93,6 +99,11 @@ function start() { // for basic concepts. const worker = new Worker('./js/worker.js', {name: 'E2EE worker'}); function setupSenderTransform(sender) { + if (window.RTCRtpScriptTransform) { + sender.transform = new RTCRtpScriptTransform(worker, {operation: 'encode'}); + return; + } + const senderStreams = sender.createEncodedStreams(); // Instead of creating the transform stream here, we do a postMessage to the worker. The first // argument is an object defined by us, the second is a list of variables that will be transferred to @@ -116,6 +127,11 @@ function setupSenderTransform(sender) { } function setupReceiverTransform(receiver) { + if (window.RTCRtpScriptTransform) { + receiver.transform = new RTCRtpScriptTransform(worker, {operation: 'decode'}); + return; + } + const receiverStreams = receiver.createEncodedStreams(); const {readable, writable} = receiverStreams; worker.postMessage({ diff --git a/src/content/insertable-streams/endtoend-encryption/js/videopipe.js b/src/content/insertable-streams/endtoend-encryption/js/videopipe.js index 71c42b317..ff50af62f 100644 --- a/src/content/insertable-streams/endtoend-encryption/js/videopipe.js +++ b/src/content/insertable-streams/endtoend-encryption/js/videopipe.js @@ -22,8 +22,9 @@ 'use strict'; // Preferring a certain codec is an expert option without GUI. +// Use VP8 by default to limit depacketization issues. // eslint-disable-next-line prefer-const -let preferredVideoCodecMimeType = undefined; +let preferredVideoCodecMimeType = 'video/VP8'; function VideoPipe(stream, forceSend, forceReceive, handler) { this.pc1 = new RTCPeerConnection({ diff --git a/src/content/insertable-streams/endtoend-encryption/js/worker.js b/src/content/insertable-streams/endtoend-encryption/js/worker.js index d49b8e773..5e3b6d07d 100644 --- a/src/content/insertable-streams/endtoend-encryption/js/worker.js +++ b/src/content/insertable-streams/endtoend-encryption/js/worker.js @@ -115,10 +115,8 @@ function decodeFunction(encodedFrame, controller) { controller.enqueue(encodedFrame); } -onmessage = async (event) => { - const {operation} = event.data; +function handleTransform(operation, readable, writable) { if (operation === 'encode') { - const {readable, writable} = event.data; const transformStream = new TransformStream({ transform: encodeFunction, }); @@ -126,14 +124,21 @@ onmessage = async (event) => { .pipeThrough(transformStream) .pipeTo(writable); } else if (operation === 'decode') { - const {readable, writable} = event.data; const transformStream = new TransformStream({ transform: decodeFunction, }); readable .pipeThrough(transformStream) .pipeTo(writable); - } else if (operation === 'setCryptoKey') { + } +} + +// Handler for messages, including transferable streams. +onmessage = (event) => { + if (event.data.operation === 'encode' || event.data.operation === 'decode') { + return handleTransform(event.data.operation, event.data.readable, event.data.writable); + } + if (event.data.operation === 'setCryptoKey') { if (event.data.currentCryptoKey !== currentCryptoKey) { currentKeyIdentifier++; } @@ -141,3 +146,11 @@ onmessage = async (event) => { useCryptoOffset = event.data.useCryptoOffset; } }; + +// Handler for RTCRtpScriptTransforms. +if (self.RTCTransformEvent) { + self.onrtctransform = (event) => { + const transformer = event.transformer; + handleTransform(transformer.options.operation, transformer.readable, transformer.writable); + }; +}