helper.js (1543B)
1 'use strict'; 2 3 // Returns an RTCEncodedVideoFrame or RTCEncodedAudioFrame 4 // on main thread. Spins up a peer connection and worker. 5 // Relies on serialization being implemented. 6 7 async function createRTCEncodedFrameFromScratch(kind) { 8 function work() { 9 onrtctransform = async ({transformer: {readable}}) => { 10 try { 11 const reader = readable.getReader(); 12 const {value, done} = await reader.read(); 13 if (done) throw {name: "done"}; 14 self.postMessage(value, {transfer: [value.data]}); 15 } catch (e) { 16 self.postMessage(e.name); 17 } 18 } 19 } 20 const worker = new Worker(`data:text/javascript,(${work.toString()})()`); 21 const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection(); 22 pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate); 23 pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate); 24 pc1.onnegotiationneeded = async () => { 25 await pc1.setLocalDescription(); await pc2.setRemoteDescription(pc1.localDescription); 26 await pc2.setLocalDescription(); await pc1.setRemoteDescription(pc2.localDescription); 27 } 28 const stream = await getNoiseStream({[kind]: true}); 29 const sender = pc1.addTrack(stream.getTracks()[0], stream); 30 sender.transform = new RTCRtpScriptTransform(worker); 31 const {data} = await new Promise(r => worker.onmessage = r); 32 return data; 33 } 34 35 function areArrayBuffersEqual(a, b) { 36 if (a.byteLength != b.byteLength) { 37 return false; 38 } 39 const ui8b = new Uint8Array(b); 40 return new Uint8Array(a).every((val, i) => val === ui8b[i]); 41 }