@wireapp/avs 0.0.3170 → 0.0.4297
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avs-worker.js +441 -0
- package/dist/avs_core.d.ts +2 -0
- package/dist/avs_core.js +2999 -4794
- package/dist/avs_pc.d.ts +9 -4
- package/dist/avs_pc.js +839 -169
- package/dist/avs_wcall.d.ts +117 -67
- package/dist/avs_wcall.js +248 -146
- package/package.json +15 -8
package/dist/avs_pc.js
CHANGED
|
@@ -1,12 +1,99 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
var ENV_FIREFOX = 1;
|
|
4
|
+
var TIMEOUT_GATHER = 2000;
|
|
4
5
|
var em_module;
|
|
5
6
|
var logFn = null;
|
|
6
7
|
var userMediaHandler = null;
|
|
7
|
-
var
|
|
8
|
+
var audioStreamHandler = null;
|
|
9
|
+
var videoStreamHandler = null;
|
|
10
|
+
var insertableLegacy = false;
|
|
11
|
+
var insertableStreams = false;
|
|
8
12
|
var pc_env = 0;
|
|
9
13
|
var pc_envver = 0;
|
|
14
|
+
var worker;
|
|
15
|
+
// Use inlined worker instead....
|
|
16
|
+
//let worker = new Worker('/worker/avs-worker.js', {name: 'AVS worker'});
|
|
17
|
+
// This is the content of the avs-worker.js file, copied here.
|
|
18
|
+
var workerContent = "\n\nvar coders = {};\n\nconst HDR_VERSION = 0;\n\n/*\nHeader\n\n 1 1 1 1 1 1\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| V=0 |E| RES |S|LEN |1|KLEN |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| KID... (length=KLEN) |\n+-------------------------------+\n| CTR... (length=LEN) |\n+-------------------------------+\n\nExtensions\n\n 0 1 2 3 4 5 6 7\n+-+-+-+-+-+-+-+-+---------------------------+\n|M| ELN | EID | VAL... (length=ELEN) |\n+-+-+-+-+-+-+-+-+---------------------------+\n*/\n\nfunction calcLen(val) {\n let l = 0;\n\n if (val == 0)\n\treturn 1;\n\n while (val != 0) {\n\tl++;\n\tval = val >>> 8;\t\n }\n\n return l;\n}\n\nfunction writeBytes(buf, p, len, val)\n{\n switch (len) {\n case 8:\n\tbuf[p] = (val >>> 56) & 0xff;\n\tp++;\n\n case 7:\n\tbuf[p] = (val >>> 48) & 0xff;\n\tp++;\n\n case 6:\n\tbuf[p] = (val >>> 40) & 0xff;\n\tp++;\n\t\n case 5:\n\tbuf[p] = (val >>> 32) & 0xff;\n\tp++;\n\n case 4:\n\tbuf[p] = (val >>> 24) & 0xff;\n\tp++;\n\n case 3:\n\tbuf[p] = (val >>> 16) & 0xff;\n\tp++;\n\n case 2:\n\tbuf[p] = (val >>> 8) & 0xff;\n\tp++;\n\n case 1:\n\tbuf[p] = val & 0xff;\n\tbreak;\n\n default:\n\treturn 0;\n }\n \n return len;\n}\n\nfunction readBytes(buf, p, len) {\n let l = len;\n let v = 0;\n\n while (l > 0) {\n\tv = v * 256;\n\tv = v + buf[p];\n\tp++;\n\tl--;\n }\n\n const lv = {\n\tlen: len,\n\tval: v\n };\n \n return lv;\n}\n\nfunction frameHeaderDecode(buf) {\n\n const MAX_EXTS = 16;\n let ext = buf[0] & 0x10;\n const flen = ((buf[1] >>> 4) & 0x7) + 1;\n const x = (buf[1] >>> 3) & 0x1;\n const klen = buf[1] & 0x7;\n let p = 2;\n let kid = -1;\n let fid = -1;\n let csrc = \"0\";\n let i = 0;\n\n if (x) {\n\tconst lv = readBytes(buf, p, klen + 1);\n\n\tp += lv.len;\n\tkid = lv.val;\n }\n else {\n\tkid = klen;\n }\n\n const lv = readBytes(buf, p, flen);\n p += lv.len;\n fid = lv.val;\n\n while(ext && p < buf.length && i < MAX_EXTS) {\n\tconst b = buf[p];\n\text = b & 0x80;\n\tconst elen = ((b >>> 4) & 0x7) + 1;\n\tconst eid = (b & 0xf);\n\n if (eid == 1 && elen == 4) {\n const csrco = readBytes(buf, p + 1, elen);\n csrc = csrco.val.toString();\n }\n p += elen + 1;\n i++;\n }\n\n if (kid < 0 || fid < 0) {\n\treturn null;\n }\n else {\n\tconst frameHdr = {\n\t len: p,\n\t frameId: fid,\n\t keyId: kid,\n\t csrc: csrc\n\t}\n\treturn frameHdr;\n }\n}\n\nfunction frameHeaderEncode(fid, kid, csrc)\n{\n const ab = new ArrayBuffer(32);\n const buf = new Uint8Array(ab);\n let sig = 0;\n let x = 0;\n let klen = 0;\n let flen = 0;\n let p = 2;\n let ext = (csrc > 0) ? 1 : 0;\n\n if (kid > 7) {\n\tx = 1;\n\tklen = calcLen(kid) - 1;\n }\n else {\n\tklen = kid;\n }\n\n flen = calcLen(fid);\n\n buf[0] = (HDR_VERSION << 5) + (ext << 4);\n buf[1] = (sig << 7) + ((flen - 1) << 4) + (x << 3) + klen;\n if (x) {\n\tp += writeBytes(buf, p, klen + 1, kid);\n }\n p += writeBytes(buf, p, flen, fid);\n\n if (csrc > 0) {\n buf[p] = 0x31;\n p++;\n p+= writeBytes(buf, p, 4, csrc);\n }\n return buf.subarray(0, p);\n}\n\nfunction xor_iv(iv, fid, kid) {\n const oiv = new Uint8Array(iv);\n\n oiv[0] = oiv[0] ^ ((fid >> 24) & 0xFF);\n oiv[1] = oiv[1] ^ ((fid >> 16) & 0xFF);\n oiv[2] = oiv[2] ^ ((fid >> 8) & 0xFF);\n oiv[3] = oiv[3] ^ ((fid ) & 0xFF);\n oiv[4] = oiv[4] ^ ((kid >> 24) & 0xFF);\n oiv[5] = oiv[5] ^ ((kid >> 16) & 0xFF);\n oiv[6] = oiv[6] ^ ((kid >> 8) & 0xFF);\n oiv[7] = oiv[7] ^ ((kid ) & 0xFF);\n\n return oiv;\n}\n\nfunction getMediaKey(self, index) {\n postMessage({\n\top: \"getMediaKey\",\n\tself: self,\n\tindex: index\n });\n}\n\nfunction getCurrentMediaKey(self, index) {\n postMessage({\n\top: \"getCurrentMediaKey\",\n\tself: self\n });\n}\n\nfunction doLog(str) {\n postMessage({\n\top: \"log\",\n\tlevel: 1,\n\tlogString: str\n });\n}\n\nfunction encryptFrame(coder, rtcFrame, controller) {\n const dataBuf = rtcFrame.data;\n const data = new Uint8Array(dataBuf);\n const t = Object.prototype.toString.call(rtcFrame);\n const isVideo = t === '[object RTCEncodedVideoFrame]';\n const userid = \"self\";\n\n const meta = rtcFrame.getMetadata();\n let ssrc = meta.synchronizationSource;\n\n if (isVideo)\n ssrc = coder.video.ssrc;\n\n if (isVideo && !coder.video.first_recv) {\n doLog(\"frame_enc: encrypt: first frame received type: video uid: \" +\n userid.substring(0,8) + \" fid: \" + coder.frameId + \" ssrc: \" + ssrc);\n coder.video.first_recv = true;\n coder.video.first_succ = false;\n }\n if (!isVideo && !coder.audio.first_recv) {\n doLog(\"frame_enc: encrypt: first frame received type: audio uid: \" +\n userid.substring(0,8) + \" fid: \" + coder.frameId + \" ssrc: \" + ssrc);\n coder.audio.first_recv = true;\n coder.audio.first_succ = false;\n }\n\n if (coder.currentKey == null) {\n getCurrentMediaKey(coder.self);\n return;\n }\n\n const baseiv = isVideo ? coder.video.iv : coder.audio.iv;\n const iv = xor_iv(baseiv, coder.frameId, coder.currentKey.id);\n\n const hdr = frameHeaderEncode(coder.frameId, coder.currentKey.id, ssrc);\n crypto.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: iv,\n tagLength: 128,\n additionalData: hdr\n },\n coder.currentKey.key,\n data\n )\n .then(function(encdata){\n const enc8 = new Uint8Array(encdata); \t \n const enc = new Uint8Array(hdr.length + enc8.length);\n \n enc.set(hdr);\n enc.set(enc8, hdr.length);\n\n rtcFrame.data = enc.buffer;\n controller.enqueue(rtcFrame);\n\n if (isVideo && !coder.video.first_succ) {\n doLog(\"frame_enc: encrypt: first frame encrypted type: video uid: \" +\n userid.substring(0,8) + \" fid: \" + coder.frameId + \" csrc: \" + ssrc);\n coder.video.first_succ = true;\n }\n if (!isVideo && !coder.audio.first_succ) {\n doLog(\"frame_enc: encrypt: first frame encrypted type: audio uid: \" +\n userid.substring(0,8) + \" fid: \" + coder.frameId + \" csrc: \" + ssrc);\n coder.audio.first_succ = true;\n }\n\n coder.frameId++;\n });\n}\n\nfunction decryptFrame(track_id, coder, rtcFrame, controller) {\n const dataBuf = rtcFrame.data;\n const data = new Uint8Array(dataBuf);\n\n const t = Object.prototype.toString.call(rtcFrame);\n const isVideo = t === '[object RTCEncodedVideoFrame]'\n\n const frameHdr = frameHeaderDecode(data);\n\n if (frameHdr == null) {\n doLog('decryptFrame: failed to decode frame header');\n return;\n }\n\n const meta = rtcFrame.getMetadata();\n let ssrc = meta.synchronizationSource.toString();\n let csrc = null;\n if (frameHdr.csrc != \"0\") {\n csrc = frameHdr.csrc;\n }\n else if (meta.contributingSources && meta.contributingSources.length > 0) {\n csrc = meta.contributingSources[0].toString();\n }\n else {\n csrc = ssrc;\n }\n\n if (!csrc) {\n doLog('decryptFrame: no csrc for ssrc ' + ssrc);\n return;\n }\n\n let uinfo = null;\n if (isVideo) {\n uinfo = coder.video.users[csrc];\n }\n else {\n uinfo = coder.audio.users[csrc];\n }\n\n if (!uinfo) {\n doLog('decryptFrame: no userinfo for csrc: ' + csrc);\n return;\n }\n \n //console.log('frame_dec: video ' + isVideo + ' ssrc ' + ssrc + ' csrc ' + csrc + ' user ' + uinfo.userid.substring(0,8));\n\n if (isVideo && uinfo.transp_ssrcv != ssrc) {\n doLog(\"frame_dec: decrypt: first frame received type: video uid: \" +\n uinfo.userid.substring(0,8) + \" fid: \" + frameHdr.frameId + \" csrc: \" + csrc + \" ssrc: \" + ssrc + \" uinfo.ssrcv: \" + uinfo.ssrcv);\n uinfo.first_succ_video = false;\n\n /* Only call videoStreamHandler for selective video */\n if (uinfo.ssrcv != ssrc) {\n for (const [key, u] of Object.entries(coder.video.users)) {\n if (u.transp_ssrcv == ssrc) {\n postMessage({\n op: \"setvstream\",\n self: coder.self,\n userid: u.userid,\n clientid: u.clientid,\n ssrc: \"0\",\n track_id: \"0\",\n });\n u.transp_ssrcv = null;\n }\n }\n\n postMessage({\n op: \"setvstream\",\n self: coder.self,\n userid: uinfo.userid,\n clientid: uinfo.clientid,\n ssrc: ssrc,\n track_id: track_id,\n });\n }\n uinfo.transp_ssrcv = ssrc;\n }\n\n if (!isVideo && !uinfo.first_recv_audio) {\n doLog(\"frame_dec: decrypt: first frame received type: audio uid: \" +\n uinfo.userid.substring(0,8) + \" fid: \" + frameHdr.frameId + \" csrc: \" + csrc);\n uinfo.first_recv_audio = true;\n uinfo.first_succ_audio = false;\n }\n /*\n console.log(\"coder[\" + coder.self + \"]\"\n\t+ \" len=\" + frameHdr.len\n\t+ \" kid=\"+ frameHdr.keyId\n\t+ \" fid=\" + frameHdr.frameId);\n */\n\n let kinfo = null;\n for (i = 0; i < coder.keys.length; i++) {\n if (coder.keys[i].id == frameHdr.keyId) {\n kinfo = coder.keys[i];\n break;\n }\n }\n\n if (!kinfo) {\n getMediaKey(coder.self, frameHdr.keyId);\n return;\n }\n\n let iv = null;\n if (isVideo) {\n iv = xor_iv(uinfo.ivv, frameHdr.frameId, frameHdr.keyId);\n }\n else {\n iv = xor_iv(uinfo.iva, frameHdr.frameId, frameHdr.keyId);\n }\n\n const hdr = data.subarray(0, frameHdr.len);\n const dec = data.subarray(frameHdr.len);\n crypto.subtle.decrypt(\n {\n name: \"AES-GCM\",\n iv: iv,\n tagLength: 128,\n additionalData: hdr\n },\n kinfo.key,\n dec\n )\n .then(function(decdata){\n rtcFrame.data = decdata;\n controller.enqueue(rtcFrame);\n if (isVideo && !uinfo.first_succ_video) {\n doLog(\"frame_dec: decrypt: first frame decrypted type: video uid: \" +\n uinfo.userid.substring(0,8) + \" fid: \" + frameHdr.frameId + \" csrc: \" + csrc);\n uinfo.first_succ_video = true;\n }\n if (!isVideo && !uinfo.first_succ_audio) {\n doLog(\"frame_dec: decrypt: first frame decrypted type: audio uid: \" +\n uinfo.userid.substring(0,8) + \" fid: \" + frameHdr.frameId + \" csrc: \" + csrc);\n uinfo.first_succ_audio = true;\n }\n })\n .catch(err => {\n console.log(err);\n });\n}\n\nfunction setupSender(readableStream, writableStream, coder) {\n\tconst transformStream = new TransformStream({\n\t transform: (frame, controller) => {encryptFrame(coder, frame, controller);},\n\t});\n\treadableStream\n .pipeThrough(transformStream)\n .pipeTo(writableStream);\n}\n\nfunction setupReceiver(readableStream, writableStream, coder, track_id) {\n const transformStream = new TransformStream({\n\t transform: (frame, controller) => {decryptFrame(track_id, coder, frame, controller);},\n });\n readableStream\n .pipeThrough(transformStream)\n .pipeTo(writableStream); \n}\n\n\nonrtctransform = (event) => {\n let transform;\n const writableStream = event.transformer.writable;\n const readableStream = event.transformer.readable;\n const coder = coders[event.transformer.options.self];\n\n if (!writableStream) {\n pc_log(LOG_LEVEL_WARN, \"onrtctransform: no writable stream\");\n return;\n }\n if (event.transformer.options.name === \"senderTransform\")\n setupSender(readableStream, writableStream, coder);\n else if (event.transformer.options.name === 'receiverTransform') {\n const track_id = event.transformer.options.track_id;\n doLog(\"onrtctransform: receiver trackid=\" + track_id);\n setupReceiver(readableStream, writableStream, coder, track_id);\n }\n};\n\n\nonmessage = async (event) => {\n const {op, self} = event.data;\n doLog('AVS worker op=' + op + ' self=' + self);\n\n let coder = coders[self];\n if (!coder) {\n\tdoLog('AVS worker: no coder for self=' + self);\n } \n /*\n const {opinfo, readableStream, writableStream} = event.data;\n const mval = opinfo.mtype === 'video' ? 1 : 0; // corresponds to enum frame_media_type\n */\n if (op === 'create') {\n\tconst { iva, ivv } = event.data;\n\tif (!coder) {\n\t coder = {\n\t\tself: self,\n\t\tframeId: Math.floor(Math.random() * 4294967295),\n\t\tcurrentKey: null,\n\t\tkeys: [],\n\t\taudio: {\n\t\t first_recv: false,\n\t\t first_succ: false,\n\t\t iv: iva,\n\t\t ssrc: \"0\",\n\t\t users: {},\n\t\t},\n\t\tvideo: {\n\t\t first_recv: false,\n\t\t first_succ: false,\n\t\t iv: ivv,\n\t\t ssrc: \"0\",\n\t\t users: {},\n\t\t},\n\t }\n\t coders[self] = coder;\n\n\t doLog('AVS worker: adding coder for self=' + self);\n\t}\n }\n else if (op === 'destroy') {\n\tcoders[self] = null;\n }\n else if (op === 'updateSsrc') {\n\tconst { ssrca, ssrcv } = event.data;\n\tcoder.audio.ssrc = ssrca;\n\tcoder.video.ssrc = ssrcv;\n }\n else if (op === 'addUser') {\n if (!coder) {\n doLog('addUser: no coder');\n return;\n }\n const {userInfo} = event.data;\n \n doLog('addUser: adding audio ssrc: '+userInfo.ssrca);\n coder.audio.users[userInfo.ssrca] = userInfo;\n if (userInfo.ssrcv != 0) {\n coder.video.users[userInfo.ssrcv] = userInfo;\n }\n }\n else if (op === 'setupSender') {\n\tconst {readableStream, writableStream} = event.data;\n\n\tsetupSender(readableStream, writableStream, coder);\n }\n else if (op === 'setupReceiver') {\n const {readableStream, writableStream} = event.data;\n\n if (!coder) {\n\t doLog('setupSender: no coder for self=' + self);\n return;\n }\n\n setupReceiver(readableStream, writableStream, coder, null);\n }\n else if (op === 'setMediaKey') {\n const {index, current, key} = event.data;\n\n doLog(\"setMediaKey: got key for: \" + self\n\t\t + \" index=\" + index + \" current=\" + current\n\t\t + \" keyLen=\" + key.length);\n\n crypto.subtle.importKey(\n \"raw\",\n key,\n \"AES-GCM\",\n false,\n [\"encrypt\", \"decrypt\"]\n )\n .then(function(k){\n let kinfo = null;\n for (i = 0; i < coder.keys.length; i++) {\n if (coder.keys[i].id == index) {\n coder.keys[i].key = k;\n kinfo = coder.keys[i];\n break;\n }\n }\n if (!kinfo) {\n kinfo = {id:index, key:k};\n coder.keys.push(kinfo);\n }\n if (index == current)\n coder.currentKey = kinfo;\n\n while (coder.keys.length > 4) {\n coder.keys.shift();\n }\n });\n } \n};\n";
|
|
19
|
+
function callStreamHandler(pc, userid, clientid, ssrc, track_id) {
|
|
20
|
+
pc_log(LOG_LEVEL_INFO, "vsh: ".concat(videoStreamHandler, " rtc: ").concat(pc.rtc, " ssrc: ").concat(ssrc));
|
|
21
|
+
var uinfo = uinfo_from_device(pc, userid, clientid);
|
|
22
|
+
if (ssrc == "0") {
|
|
23
|
+
if (uinfo) {
|
|
24
|
+
uinfo.video_track_id = "0";
|
|
25
|
+
}
|
|
26
|
+
if (videoStreamHandler) {
|
|
27
|
+
pc_log(LOG_LEVEL_INFO, "calling vsh(".concat(pc.convid.substring(0, 8), ", ").concat(userid.substring(0, 8), ", ").concat(clientid.substring(0, 4), ") to remove renderer"));
|
|
28
|
+
videoStreamHandler(pc.convid, userid, clientid, null);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (pc.rtc) {
|
|
32
|
+
if (pc_env === ENV_FIREFOX) {
|
|
33
|
+
pc.rtc.getTransceivers().forEach(function (trans) {
|
|
34
|
+
var track = trans.receiver.track;
|
|
35
|
+
if (track.kind != 'video')
|
|
36
|
+
return;
|
|
37
|
+
pc_log(LOG_LEVEL_INFO, "vsh: id:".concat(track.id, " looking for: ").concat(track_id));
|
|
38
|
+
if (track.id === track_id) {
|
|
39
|
+
if (uinfo) {
|
|
40
|
+
uinfo.video_track_id = track_id;
|
|
41
|
+
}
|
|
42
|
+
var stream = new MediaStream([trans.receiver.track]);
|
|
43
|
+
if (videoStreamHandler) {
|
|
44
|
+
pc_log(LOG_LEVEL_INFO, "calling vsh(".concat(pc.convid.substring(0, 8), ", ").concat(userid.substring(0, 8), ", ").concat(clientid.substring(0, 4), ") with 1 stream"));
|
|
45
|
+
videoStreamHandler(pc.convid, userid, clientid, [stream]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
var label_1 = pc.streams[ssrc];
|
|
52
|
+
pc.rtc.getTransceivers().forEach(function (trans) {
|
|
53
|
+
var track = trans.receiver.track;
|
|
54
|
+
pc_log(LOG_LEVEL_INFO, "vsh: label:".concat(track.label, " id:").concat(track.id, " looking for: ").concat(label_1));
|
|
55
|
+
if (trans.receiver.track.label === label_1) {
|
|
56
|
+
if (uinfo) {
|
|
57
|
+
uinfo.video_track_id = track.id;
|
|
58
|
+
}
|
|
59
|
+
var stream = new MediaStream([trans.receiver.track]);
|
|
60
|
+
if (videoStreamHandler) {
|
|
61
|
+
pc_log(LOG_LEVEL_INFO, "calling vsh(".concat(pc.convid.substring(0, 8), ", ").concat(userid.substring(0, 8), ", ").concat(clientid.substring(0, 4), ") with 1 stream"));
|
|
62
|
+
videoStreamHandler(pc.convid, userid, clientid, [stream]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function createWorker() {
|
|
70
|
+
var blob = new Blob([workerContent], { type: 'text/javascript' });
|
|
71
|
+
var url = URL.createObjectURL(blob);
|
|
72
|
+
worker = new Worker(url, { name: 'AVS worker' });
|
|
73
|
+
worker.onmessage = function (event) {
|
|
74
|
+
var _a = event.data, op = _a.op, self = _a.self;
|
|
75
|
+
if (op === 'getMediaKey') {
|
|
76
|
+
var index = event.data.index;
|
|
77
|
+
ccallGetMediaKey(self, index);
|
|
78
|
+
}
|
|
79
|
+
else if (op === 'getCurrentMediaKey') {
|
|
80
|
+
ccallGetCurrentMediaKey(self);
|
|
81
|
+
}
|
|
82
|
+
else if (op === 'log') {
|
|
83
|
+
var _b = event.data, level = _b.level, logString = _b.logString;
|
|
84
|
+
pc_log(level, logString);
|
|
85
|
+
}
|
|
86
|
+
else if (op === 'setvstream') {
|
|
87
|
+
var _c = event.data, userid = _c.userid, clientid = _c.clientid, ssrc = _c.ssrc, track_id = _c.track_id;
|
|
88
|
+
pc_log(LOG_LEVEL_INFO, "setvstream: called");
|
|
89
|
+
var pcs = connectionsStore.getPeerConnectionBySelf(self);
|
|
90
|
+
if (pcs.length == 1) {
|
|
91
|
+
pc_log(LOG_LEVEL_INFO, "setvstream: calling videoStreamHandler: pc=".concat(pcs[0], ", ").concat(userid, "/").concat(clientid, " ssrc=").concat(ssrc));
|
|
92
|
+
callStreamHandler(pcs[0], userid, clientid, ssrc, track_id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
10
97
|
/* The following constants closely reflect the values
|
|
11
98
|
* defined in the the C-land counterpart peerconnection_js.c
|
|
12
99
|
*/
|
|
@@ -38,6 +125,9 @@ var LOG_LEVEL_ERROR = 3;
|
|
|
38
125
|
var CALL_TYPE_NORMAL = 0;
|
|
39
126
|
var CALL_TYPE_VIDEO = 1;
|
|
40
127
|
var CALL_TYPE_FORCED_AUDIO = 2;
|
|
128
|
+
var CONV_TYPE_ONEONONE = 0;
|
|
129
|
+
var CONV_TYPE_GROUP = 1;
|
|
130
|
+
var CONV_TYPE_CONFERENCE = 2;
|
|
41
131
|
var connectionsStore = (function () {
|
|
42
132
|
var peerConnections = [null];
|
|
43
133
|
var dataChannels = [null];
|
|
@@ -64,6 +154,11 @@ var connectionsStore = (function () {
|
|
|
64
154
|
return !!pc && pc.convid === convid;
|
|
65
155
|
});
|
|
66
156
|
},
|
|
157
|
+
getPeerConnectionBySelf: function (self) {
|
|
158
|
+
return peerConnections.filter(function (pc) {
|
|
159
|
+
return !!pc && pc.self == self;
|
|
160
|
+
});
|
|
161
|
+
},
|
|
67
162
|
removePeerConnection: function (index) { return removeItem(peerConnections, index); },
|
|
68
163
|
storeDataChannel: function (dataChannel) {
|
|
69
164
|
return storeItem(dataChannels, dataChannel);
|
|
@@ -72,9 +167,43 @@ var connectionsStore = (function () {
|
|
|
72
167
|
removeDataChannel: function (index) { return removeItem(dataChannels, index); }
|
|
73
168
|
};
|
|
74
169
|
})();
|
|
75
|
-
function pc_log(level, msg) {
|
|
170
|
+
function pc_log(level, msg, err) {
|
|
171
|
+
if (err === void 0) { err = null; }
|
|
172
|
+
em_module.ccall("pc_log", null, ["number", "string"], [level, msg]);
|
|
173
|
+
/* Log now goes through AVS for anonymization
|
|
76
174
|
if (logFn)
|
|
77
|
-
|
|
175
|
+
logFn(level, msg, err);
|
|
176
|
+
*/
|
|
177
|
+
}
|
|
178
|
+
function uinfo_from_ssrca(pc, ssrc) {
|
|
179
|
+
for (var _i = 0, _a = Object.keys(pc.users); _i < _a.length; _i++) {
|
|
180
|
+
var key = _a[_i];
|
|
181
|
+
var uinfo = pc.users[key];
|
|
182
|
+
if (uinfo.ssrca === ssrc) {
|
|
183
|
+
return uinfo;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
function uinfo_from_device(pc, user_id, client_id) {
|
|
189
|
+
for (var _i = 0, _a = Object.keys(pc.users); _i < _a.length; _i++) {
|
|
190
|
+
var key = _a[_i];
|
|
191
|
+
var uinfo = pc.users[key];
|
|
192
|
+
if (uinfo.userid === user_id && uinfo.clientid === client_id) {
|
|
193
|
+
return uinfo;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
function uinfo_from_video_track_id(pc, track_id) {
|
|
199
|
+
for (var _i = 0, _a = Object.keys(pc.users); _i < _a.length; _i++) {
|
|
200
|
+
var key = _a[_i];
|
|
201
|
+
var uinfo = pc.users[key];
|
|
202
|
+
if (uinfo.video_track_id === track_id) {
|
|
203
|
+
return uinfo;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
78
207
|
}
|
|
79
208
|
function replace_track(pc, newTrack) {
|
|
80
209
|
var rtc = pc.rtc;
|
|
@@ -83,25 +212,33 @@ function replace_track(pc, newTrack) {
|
|
|
83
212
|
var senders = rtc.getSenders();
|
|
84
213
|
if (!senders)
|
|
85
214
|
return false;
|
|
86
|
-
|
|
87
|
-
var sender = senders_1[_i];
|
|
215
|
+
var _loop_1 = function (sender) {
|
|
88
216
|
if (!sender)
|
|
89
|
-
continue;
|
|
217
|
+
return "continue";
|
|
90
218
|
if (!sender.track)
|
|
91
|
-
continue;
|
|
219
|
+
return "continue";
|
|
92
220
|
if (sender.track.kind === newTrack.kind) {
|
|
93
221
|
var oldTrack = sender.track;
|
|
94
222
|
if (!oldTrack) {
|
|
95
|
-
pc_log(
|
|
223
|
+
pc_log(LOG_LEVEL_INFO, 'replace_track: oldtrack null');
|
|
96
224
|
}
|
|
97
225
|
else {
|
|
98
|
-
var
|
|
99
|
-
sender.replaceTrack(newTrack)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
226
|
+
var enabled_1 = oldTrack.enabled;
|
|
227
|
+
sender.replaceTrack(newTrack).then(function () {
|
|
228
|
+
if (!!sender && !!sender.track) {
|
|
229
|
+
sender.track.enabled = enabled_1;
|
|
230
|
+
pc_log(LOG_LEVEL_INFO, "replace_track: kind=".concat(newTrack.kind, " enabled=").concat(sender.track.enabled));
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
return { value: true };
|
|
103
234
|
}
|
|
104
235
|
}
|
|
236
|
+
};
|
|
237
|
+
for (var _i = 0, senders_1 = senders; _i < senders_1.length; _i++) {
|
|
238
|
+
var sender = senders_1[_i];
|
|
239
|
+
var state_1 = _loop_1(sender);
|
|
240
|
+
if (typeof state_1 === "object")
|
|
241
|
+
return state_1.value;
|
|
105
242
|
}
|
|
106
243
|
return false;
|
|
107
244
|
}
|
|
@@ -109,9 +246,10 @@ function update_tracks(pc, stream) {
|
|
|
109
246
|
var rtc = pc.rtc;
|
|
110
247
|
var tracks = stream.getTracks();
|
|
111
248
|
var found = false;
|
|
112
|
-
pc_log(LOG_LEVEL_INFO, "update_tracks: pc="
|
|
113
|
-
if (!rtc)
|
|
114
|
-
return;
|
|
249
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: pc=".concat(pc.self, " tracks=").concat(tracks.length));
|
|
250
|
+
if (!rtc) {
|
|
251
|
+
return Promise.resolve();
|
|
252
|
+
}
|
|
115
253
|
var senders = rtc.getSenders();
|
|
116
254
|
for (var _i = 0, senders_2 = senders; _i < senders_2.length; _i++) {
|
|
117
255
|
var sender = senders_2[_i];
|
|
@@ -125,9 +263,9 @@ function update_tracks(pc, stream) {
|
|
|
125
263
|
for (var _a = 0, tracks_1 = tracks; _a < tracks_1.length; _a++) {
|
|
126
264
|
var track = tracks_1[_a];
|
|
127
265
|
if (track)
|
|
128
|
-
pc_log(
|
|
266
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: kind=".concat(track.kind, " sender=").concat(sender.track.kind));
|
|
129
267
|
else
|
|
130
|
-
pc_log(
|
|
268
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: sender.track=".concat(sender.track, " track=").concat(track));
|
|
131
269
|
if (sender.track) {
|
|
132
270
|
if (sender.track.kind === track.kind) {
|
|
133
271
|
found = true;
|
|
@@ -137,10 +275,15 @@ function update_tracks(pc, stream) {
|
|
|
137
275
|
}
|
|
138
276
|
}
|
|
139
277
|
if (!found) {
|
|
140
|
-
if (sender.track)
|
|
278
|
+
if (sender.track) {
|
|
141
279
|
sender.track.enabled = false;
|
|
280
|
+
}
|
|
142
281
|
}
|
|
143
282
|
}
|
|
283
|
+
var videoSenderUpdates = [];
|
|
284
|
+
// We have to check old API, because in old API the transceiver with mid==1 is a receiver and in the new API it is
|
|
285
|
+
// a sender. We have to avoid adding tracks if transceiver is receiver.
|
|
286
|
+
var isOldAPI = rtc.getTransceivers().some(function (t) { return t.mid === "video"; });
|
|
144
287
|
tracks.forEach(function (track) {
|
|
145
288
|
if (track.kind === 'video') {
|
|
146
289
|
pc.sending_video = true;
|
|
@@ -149,10 +292,71 @@ function update_tracks(pc, stream) {
|
|
|
149
292
|
track.enabled = !pc.muted;
|
|
150
293
|
}
|
|
151
294
|
if (!replace_track(pc, track)) {
|
|
152
|
-
pc_log(LOG_LEVEL_INFO, "update_tracks: adding track of kind="
|
|
153
|
-
|
|
295
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: adding track of kind=".concat(track.kind, ", id=").concat(track.id));
|
|
296
|
+
if (track.kind === 'video' && pc.conv_type !== CONV_TYPE_ONEONONE) {
|
|
297
|
+
var transceivers = rtc.getTransceivers();
|
|
298
|
+
var _loop_2 = function (trans) {
|
|
299
|
+
if ((trans.mid === 'video' && isOldAPI) || (trans.mid === '1' && !isOldAPI)) {
|
|
300
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: adjust");
|
|
301
|
+
var _a = getEncodingParameter(trans.sender, pc.vstate === PC_VIDEO_STATE_SCREENSHARE), params_1 = _a.params, layerFound = _a.layerFound;
|
|
302
|
+
pc_log(LOG_LEVEL_INFO, 'add track: ' + layerFound);
|
|
303
|
+
rtc.addTrack(track, stream);
|
|
304
|
+
if (layerFound) {
|
|
305
|
+
videoSenderUpdates.push(trans.sender.setParameters(params_1).catch(function (e) { return pc_log(LOG_LEVEL_ERROR, "update_tracks: set params ".concat(e)); })
|
|
306
|
+
.then(function () {
|
|
307
|
+
pc_log(LOG_LEVEL_INFO, 'setParameters: ' + JSON.stringify(params_1));
|
|
308
|
+
})
|
|
309
|
+
.then());
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
for (var _i = 0, transceivers_1 = transceivers; _i < transceivers_1.length; _i++) {
|
|
314
|
+
var trans = transceivers_1[_i];
|
|
315
|
+
_loop_2(trans);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
rtc.addTrack(track, stream);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
// Either the codecs did not need to be adjusted because we are in a 1:1 call, or we are not sending a video track.
|
|
324
|
+
// In that case, there is no need to wait for the asynchronous process
|
|
325
|
+
if (videoSenderUpdates.length === 0) {
|
|
326
|
+
return Promise.resolve();
|
|
327
|
+
}
|
|
328
|
+
// Wait until setup is finish
|
|
329
|
+
return Promise.all(videoSenderUpdates).catch(function (e) {
|
|
330
|
+
pc_log(LOG_LEVEL_ERROR, "update_tracks: error=".concat(e));
|
|
331
|
+
}).then();
|
|
332
|
+
}
|
|
333
|
+
function getEncodingParameter(sender, isScreenShare) {
|
|
334
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: adjust");
|
|
335
|
+
var params = sender.getParameters();
|
|
336
|
+
if (!params.encodings) {
|
|
337
|
+
pc_log(LOG_LEVEL_INFO, "update_tracks: no params");
|
|
338
|
+
params.encodings = [];
|
|
339
|
+
}
|
|
340
|
+
var layerFound = false;
|
|
341
|
+
params.encodings.forEach(function (coding) {
|
|
342
|
+
if (coding.rid === 'l') {
|
|
343
|
+
//@ts-ignore
|
|
344
|
+
coding.scalabilityMode = 'L1T1';
|
|
345
|
+
coding.active = !isScreenShare;
|
|
346
|
+
coding.scaleResolutionDownBy = 2.0;
|
|
347
|
+
coding.maxBitrate = 500000;
|
|
348
|
+
layerFound = true;
|
|
349
|
+
}
|
|
350
|
+
if (coding.rid === 'h') {
|
|
351
|
+
//@ts-ignore
|
|
352
|
+
coding.scalabilityMode = 'L1T1';
|
|
353
|
+
coding.scaleResolutionDownBy = 1.0;
|
|
354
|
+
coding.active = true;
|
|
355
|
+
coding.maxBitrate = isScreenShare ? 1500000 : 3000000;
|
|
356
|
+
layerFound = true;
|
|
154
357
|
}
|
|
155
358
|
});
|
|
359
|
+
return { params: params, layerFound: layerFound };
|
|
156
360
|
}
|
|
157
361
|
function sigState(stateStr) {
|
|
158
362
|
var state = PC_SIG_STATE_UNKNOWN;
|
|
@@ -203,29 +407,46 @@ function ccallDcStateChangeHandler(pc, state) {
|
|
|
203
407
|
function ccallDcDataHandler(pc, data) {
|
|
204
408
|
em_module.ccall("dc_data_handler", null, ["number", "string", "number"], [pc.self, data, data.length]);
|
|
205
409
|
}
|
|
410
|
+
function ccallGetMediaKey(self, index) {
|
|
411
|
+
em_module.ccall("pc_get_media_key", null, ["number", "number"], [self, index]);
|
|
412
|
+
}
|
|
413
|
+
function ccallGetCurrentMediaKey(self) {
|
|
414
|
+
em_module.ccall("pc_get_current_media_key", null, ["number"], [self]);
|
|
415
|
+
}
|
|
416
|
+
function gatheringComplete(pc) {
|
|
417
|
+
if (pc.gatherTimer != null) {
|
|
418
|
+
clearTimeout(pc.gatherTimer);
|
|
419
|
+
pc.gatherTimer = null;
|
|
420
|
+
}
|
|
421
|
+
var rtc = pc.rtc;
|
|
422
|
+
if (!rtc) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
var sdp = rtc.localDescription;
|
|
426
|
+
if (!sdp) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
ccallGatheringHandler(pc, sdp.type.toString(), sdp.sdp.toString());
|
|
430
|
+
}
|
|
206
431
|
function gatheringHandler(pc) {
|
|
207
432
|
var rtc = pc.rtc;
|
|
208
433
|
if (!rtc) {
|
|
209
434
|
return;
|
|
210
435
|
}
|
|
211
436
|
var state = rtc.iceGatheringState;
|
|
212
|
-
pc_log(LOG_LEVEL_INFO, "ice gathering state="
|
|
437
|
+
pc_log(LOG_LEVEL_INFO, "ice gathering state=".concat(state));
|
|
213
438
|
switch (state) {
|
|
214
439
|
case "new":
|
|
215
440
|
break;
|
|
216
441
|
case "gathering":
|
|
217
442
|
break;
|
|
218
443
|
case "complete":
|
|
219
|
-
|
|
220
|
-
if (!sdp) {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
ccallGatheringHandler(pc, sdp.type.toString(), sdp.sdp.toString());
|
|
444
|
+
gatheringComplete(pc);
|
|
224
445
|
break;
|
|
225
446
|
}
|
|
226
447
|
}
|
|
227
448
|
function negotiationHandler(pc) {
|
|
228
|
-
pc_log(LOG_LEVEL_INFO, "negotiationHandler: "
|
|
449
|
+
pc_log(LOG_LEVEL_INFO, "negotiationHandler: ".concat(pc.self));
|
|
229
450
|
}
|
|
230
451
|
function signallingHandler(pc) {
|
|
231
452
|
var rtc = pc.rtc;
|
|
@@ -233,7 +454,7 @@ function signallingHandler(pc) {
|
|
|
233
454
|
return;
|
|
234
455
|
}
|
|
235
456
|
var stateStr = rtc.signalingState;
|
|
236
|
-
pc_log(LOG_LEVEL_INFO, "signalingHandler: state: "
|
|
457
|
+
pc_log(LOG_LEVEL_INFO, "signalingHandler: state: ".concat(stateStr));
|
|
237
458
|
ccallSignallingHandler(pc, sigState(stateStr));
|
|
238
459
|
}
|
|
239
460
|
function setMute(pc) {
|
|
@@ -253,52 +474,28 @@ function setMute(pc) {
|
|
|
253
474
|
function candidateHandler(pc, cand) {
|
|
254
475
|
var mindex = cand ? cand.sdpMLineIndex : null;
|
|
255
476
|
if (cand !== null)
|
|
256
|
-
pc_log(
|
|
477
|
+
pc_log(LOG_LEVEL_INFO, "candidateHandler: cand=".concat(cand.candidate, " type=").concat(cand.type, " mindex=").concat(mindex));
|
|
257
478
|
else {
|
|
258
|
-
pc_log(
|
|
479
|
+
pc_log(LOG_LEVEL_INFO, "candidateHandler: cand=NULL");
|
|
259
480
|
}
|
|
260
481
|
if (!pc || !pc.rtc)
|
|
261
482
|
return;
|
|
262
483
|
if (!cand) {
|
|
263
484
|
pc_log(LOG_LEVEL_INFO, 'candidateHandler: end-of-candidates');
|
|
264
|
-
|
|
265
|
-
if (sdp)
|
|
266
|
-
ccallGatheringHandler(pc, sdp.type.toString(), sdp.sdp.toString());
|
|
485
|
+
gatheringComplete(pc);
|
|
267
486
|
return;
|
|
268
487
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
pc_log(LOG_LEVEL_DEBUG, "candidateHandler: adding mindex=" + mindex);
|
|
274
|
-
pc.cands[mindex] = {
|
|
275
|
-
mindex: mindex,
|
|
276
|
-
hasRelay: false
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
488
|
+
/* As soon as we get the first relay, we start a gathering timer
|
|
489
|
+
* this was we ensure that gathering never takes more than the
|
|
490
|
+
* timeout period.
|
|
491
|
+
*/
|
|
281
492
|
if (cand.type === 'relay') {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (mindex != null) {
|
|
288
|
-
var rmid = pc.cands[mindex];
|
|
289
|
-
if (rmid)
|
|
290
|
-
rmid.hasRelay = true;
|
|
291
|
-
}
|
|
292
|
-
for (var _i = 0, _a = pc.cands; _i < _a.length; _i++) {
|
|
293
|
-
var cc = _a[_i];
|
|
294
|
-
if (cc && !cc.hasRelay) {
|
|
295
|
-
pc_log(LOG_LEVEL_DEBUG, "candidateHandler: mindex=" + cc.mindex + " still missing relay");
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
493
|
+
if (pc.gatherTimer == null) {
|
|
494
|
+
pc.gatherTimer = setTimeout(function () {
|
|
495
|
+
pc.gatherTimer = null;
|
|
496
|
+
gatheringComplete(pc);
|
|
497
|
+
}, TIMEOUT_GATHER);
|
|
299
498
|
}
|
|
300
|
-
pc_log(LOG_LEVEL_INFO, 'candidateHandler: relay(s) found, finished gathering');
|
|
301
|
-
ccallGatheringHandler(pc, sdp.type.toString(), sdp.sdp.toString());
|
|
302
499
|
}
|
|
303
500
|
}
|
|
304
501
|
function connectionHandler(pc) {
|
|
@@ -306,42 +503,53 @@ function connectionHandler(pc) {
|
|
|
306
503
|
if (!rtc) {
|
|
307
504
|
return;
|
|
308
505
|
}
|
|
309
|
-
var state = rtc.
|
|
310
|
-
pc_log(LOG_LEVEL_INFO, "connectionHandler state: "
|
|
506
|
+
var state = rtc.connectionState;
|
|
507
|
+
pc_log(LOG_LEVEL_INFO, "connectionHandler state: ".concat(state));
|
|
311
508
|
ccallConnectionHandler(pc, state);
|
|
312
509
|
setMute(pc);
|
|
313
510
|
}
|
|
314
511
|
function setupDataChannel(pc, dc) {
|
|
315
512
|
var dcHnd = connectionsStore.storeDataChannel(dc);
|
|
316
513
|
dc.onopen = function () {
|
|
317
|
-
pc_log(
|
|
514
|
+
pc_log(LOG_LEVEL_INFO, "dc-opened");
|
|
318
515
|
ccallDcStateChangeHandler(pc, DC_STATE_OPEN);
|
|
319
516
|
};
|
|
320
517
|
dc.onclose = function () {
|
|
321
|
-
pc_log(
|
|
518
|
+
pc_log(LOG_LEVEL_INFO, "dc-closed");
|
|
322
519
|
ccallDcStateChangeHandler(pc, DC_STATE_CLOSED);
|
|
323
520
|
};
|
|
324
|
-
dc.onerror = function () {
|
|
325
|
-
|
|
326
|
-
|
|
521
|
+
dc.onerror = function (event) {
|
|
522
|
+
if (event instanceof RTCErrorEvent) {
|
|
523
|
+
pc_log(LOG_LEVEL_INFO, "dc-error: ".concat(event.error));
|
|
524
|
+
ccallDcStateChangeHandler(pc, DC_STATE_ERROR);
|
|
525
|
+
}
|
|
327
526
|
};
|
|
328
527
|
dc.onmessage = function (event) {
|
|
329
|
-
pc_log(
|
|
528
|
+
pc_log(LOG_LEVEL_INFO, "dc-onmessage: data=".concat(event.data.length));
|
|
330
529
|
ccallDcDataHandler(pc, event.data.toString());
|
|
331
530
|
};
|
|
332
531
|
return dcHnd;
|
|
333
532
|
}
|
|
334
533
|
function dataChannelHandler(pc, event) {
|
|
335
534
|
var dc = event.channel;
|
|
336
|
-
pc_log(LOG_LEVEL_INFO, "dataChannelHandler: "
|
|
535
|
+
pc_log(LOG_LEVEL_INFO, "dataChannelHandler: ".concat(dc));
|
|
337
536
|
var dcHnd = setupDataChannel(pc, dc);
|
|
338
537
|
ccallDcEstabHandler(pc, dcHnd);
|
|
339
538
|
}
|
|
340
539
|
function pc_SetEnv(env) {
|
|
540
|
+
pc_log(LOG_LEVEL_INFO, "setEnv=".concat(env));
|
|
341
541
|
pc_env = env;
|
|
342
542
|
}
|
|
343
|
-
function pc_New(self, convidPtr) {
|
|
344
|
-
pc_log(
|
|
543
|
+
function pc_New(self, convidPtr, audioIvPtr, videoIvPtr, ivlen) {
|
|
544
|
+
pc_log(LOG_LEVEL_INFO, "pc_New");
|
|
545
|
+
var iva = new ArrayBuffer(ivlen);
|
|
546
|
+
var aptr = new Uint8Array(em_module.HEAPU8.buffer, audioIvPtr, ivlen);
|
|
547
|
+
var iva8 = new Uint8Array(iva);
|
|
548
|
+
iva8.set(aptr);
|
|
549
|
+
var ivv = new ArrayBuffer(ivlen);
|
|
550
|
+
var vptr = new Uint8Array(em_module.HEAPU8.buffer, videoIvPtr, ivlen);
|
|
551
|
+
var ivv8 = new Uint8Array(ivv);
|
|
552
|
+
ivv8.set(vptr);
|
|
345
553
|
var pc = {
|
|
346
554
|
self: self,
|
|
347
555
|
convid: em_module.UTF8ToString(convidPtr),
|
|
@@ -352,55 +560,127 @@ function pc_New(self, convidPtr) {
|
|
|
352
560
|
vstate: PC_VIDEO_STATE_STOPPED,
|
|
353
561
|
sending_video: false,
|
|
354
562
|
call_type: CALL_TYPE_NORMAL,
|
|
563
|
+
conv_type: CONV_TYPE_ONEONONE,
|
|
355
564
|
muted: false,
|
|
356
|
-
|
|
565
|
+
users: {},
|
|
566
|
+
iva: iva8,
|
|
567
|
+
ivv: ivv8,
|
|
568
|
+
stats: {
|
|
569
|
+
ploss: 0,
|
|
570
|
+
lastploss: 0,
|
|
571
|
+
bytes: 0,
|
|
572
|
+
lastbytes: 0,
|
|
573
|
+
recv_apkts: 0,
|
|
574
|
+
recv_vpkts: 0,
|
|
575
|
+
sent_apkts: 0,
|
|
576
|
+
sent_vpkts: 0,
|
|
577
|
+
rtt: 0
|
|
578
|
+
},
|
|
579
|
+
streams: {},
|
|
580
|
+
gatherTimer: null
|
|
357
581
|
};
|
|
582
|
+
worker.postMessage({ op: 'create', self: pc.self, iva: iva8, ivv: ivv8 });
|
|
358
583
|
var hnd = connectionsStore.storePeerConnection(pc);
|
|
359
584
|
return hnd;
|
|
360
585
|
}
|
|
361
|
-
function pc_Create(hnd) {
|
|
586
|
+
function pc_Create(hnd, privacy, conv_type) {
|
|
362
587
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
363
588
|
if (pc == null) {
|
|
364
589
|
return;
|
|
365
590
|
}
|
|
591
|
+
pc.conv_type = conv_type;
|
|
592
|
+
var transportPolicy = privacy !== 0 ? "relay" : "all";
|
|
593
|
+
var useEncoding = pc.conv_type === CONV_TYPE_CONFERENCE;
|
|
366
594
|
var config = {
|
|
367
595
|
bundlePolicy: "max-bundle",
|
|
368
596
|
iceServers: pc.turnServers,
|
|
369
|
-
rtcpMuxPolicy: 'require'
|
|
597
|
+
rtcpMuxPolicy: 'require',
|
|
598
|
+
iceTransportPolicy: transportPolicy,
|
|
599
|
+
encodedInsertableStreams: useEncoding,
|
|
600
|
+
forceEncodedVideoInsertableStreams: useEncoding,
|
|
601
|
+
forceEncodedAudioInsertableStreams: useEncoding,
|
|
370
602
|
};
|
|
371
|
-
pc_log(LOG_LEVEL_INFO, "pc_Create: configuring: "
|
|
603
|
+
pc_log(LOG_LEVEL_INFO, "pc_Create: configuring: ".concat(pc.turnServers.length, " TURN servers"));
|
|
372
604
|
var rtc = new RTCPeerConnection(config);
|
|
605
|
+
pc.rtc = rtc;
|
|
373
606
|
rtc.onicegatheringstatechange = function () { return gatheringHandler(pc); };
|
|
374
|
-
rtc.
|
|
607
|
+
rtc.onconnectionstatechange = function () { return connectionHandler(pc); };
|
|
375
608
|
rtc.onicecandidate = function (event) { return candidateHandler(pc, event.candidate); };
|
|
376
609
|
rtc.onsignalingstatechange = function (event) { return signallingHandler(pc); };
|
|
377
610
|
rtc.ondatachannel = function (event) { return dataChannelHandler(pc, event); };
|
|
378
611
|
rtc.onnegotiationneeded = function () { return negotiationHandler(pc); };
|
|
612
|
+
var label = '';
|
|
379
613
|
rtc.ontrack = function (event) {
|
|
380
|
-
pc_log(LOG_LEVEL_INFO, "onTrack:
|
|
614
|
+
pc_log(LOG_LEVEL_INFO, "onTrack: self=".concat(pc.self, " convid=").concat(pc.convid.substring(0, 8), " userid=").concat(pc.remote_userid.substring(0, 8), "/").concat(pc.remote_clientid.substring(0, 4), " streams=").concat(event.streams.length));
|
|
381
615
|
if (event.streams && event.streams.length > 0) {
|
|
382
616
|
for (var _i = 0, _a = event.streams; _i < _a.length; _i++) {
|
|
383
617
|
var stream = _a[_i];
|
|
384
|
-
pc_log(LOG_LEVEL_INFO, "onTrack: convid="
|
|
618
|
+
pc_log(LOG_LEVEL_INFO, "onTrack: convid=".concat(pc.convid.substring(0, 8), " stream=").concat(stream));
|
|
385
619
|
for (var _b = 0, _c = stream.getTracks(); _b < _c.length; _b++) {
|
|
386
620
|
var track = _c[_b];
|
|
387
|
-
if (track)
|
|
388
|
-
|
|
621
|
+
if (track) {
|
|
622
|
+
if (pc_env === ENV_FIREFOX)
|
|
623
|
+
label = track.id;
|
|
624
|
+
else
|
|
625
|
+
label = track.label;
|
|
626
|
+
pc_log(LOG_LEVEL_INFO, "onTrack: convid=".concat(pc.convid.substring(0, 8), " track=").concat(track.id, "/").concat(track.label, "=>").concat(label, " kind=").concat(track.kind, " enabled=").concat(track.enabled, "/").concat(track.muted, "/undefined/").concat(track.readyState, " remote=undefined"));
|
|
627
|
+
if (!track.enabled)
|
|
628
|
+
track.enabled = true;
|
|
629
|
+
if (pc.conv_type === CONV_TYPE_CONFERENCE) {
|
|
630
|
+
try {
|
|
631
|
+
setupReceiverTransform(pc, event.receiver);
|
|
632
|
+
}
|
|
633
|
+
catch (err) {
|
|
634
|
+
pc_log(LOG_LEVEL_WARN, "onTrack: setupReceiverTransform failed: " + err, err);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
389
638
|
}
|
|
390
639
|
}
|
|
391
640
|
}
|
|
392
|
-
if (
|
|
393
|
-
|
|
641
|
+
if (event.track.kind == "audio" && audioStreamHandler) {
|
|
642
|
+
pc_log(LOG_LEVEL_INFO, "onTrack: calling ash(".concat(pc.convid.substring(0, 8), ", ").concat(label, ") with ").concat(event.streams.length, " streams"));
|
|
643
|
+
audioStreamHandler(pc.convid, hnd.toString() + label, event.streams);
|
|
644
|
+
}
|
|
645
|
+
if (event.track.kind == "video" && videoStreamHandler) {
|
|
646
|
+
var userid = pc.remote_userid;
|
|
647
|
+
var clientid = pc.remote_clientid;
|
|
648
|
+
// @TODO: Remove, because the `keys` from `pc.users[]` is are random strings and not track.id or track.label, so means `uinfo` will be `undefined` everytime!
|
|
649
|
+
var uinfo = pc.users[label];
|
|
650
|
+
if (uinfo) {
|
|
651
|
+
userid = uinfo.userid;
|
|
652
|
+
clientid = uinfo.clientid;
|
|
653
|
+
}
|
|
654
|
+
if (userid != "sft" && userid != "") {
|
|
655
|
+
pc_log(LOG_LEVEL_INFO, "onTrack: calling vsh(".concat(pc.convid.substring(0, 8), ", ").concat(userid.substring(0, 8), ", ").concat(clientid.substring(0, 4), ") with ").concat(event.streams.length, " streams"));
|
|
656
|
+
videoStreamHandler(pc.convid, userid, clientid, event.streams);
|
|
657
|
+
}
|
|
394
658
|
}
|
|
395
659
|
};
|
|
396
|
-
pc.rtc = rtc;
|
|
397
660
|
}
|
|
398
661
|
function pc_Close(hnd) {
|
|
399
|
-
pc_log(LOG_LEVEL_INFO, "pc_Close: hnd="
|
|
662
|
+
pc_log(LOG_LEVEL_INFO, "pc_Close: hnd=".concat(hnd));
|
|
400
663
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
401
664
|
if (pc == null) {
|
|
402
665
|
return;
|
|
403
666
|
}
|
|
667
|
+
if (pc.rtc) {
|
|
668
|
+
pc.rtc.getTransceivers().forEach(function (trans) {
|
|
669
|
+
var track = trans.receiver.track;
|
|
670
|
+
if (track && track.kind === "audio") {
|
|
671
|
+
var label = '';
|
|
672
|
+
if (pc_env == ENV_FIREFOX)
|
|
673
|
+
label = track.id;
|
|
674
|
+
else
|
|
675
|
+
label = track.label;
|
|
676
|
+
if (audioStreamHandler && pc.rtc) {
|
|
677
|
+
pc_log(LOG_LEVEL_INFO, "pc_Close: calling ash(".concat(pc.convid.substring(0, 8), ", ").concat(label, ") with 0 streams"));
|
|
678
|
+
audioStreamHandler(pc.convid, hnd.toString() + label, null);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
worker.postMessage({ op: 'destroy', self: pc.self });
|
|
404
684
|
connectionsStore.removePeerConnection(hnd);
|
|
405
685
|
var rtc = pc.rtc;
|
|
406
686
|
if (!rtc) {
|
|
@@ -410,7 +690,7 @@ function pc_Close(hnd) {
|
|
|
410
690
|
pc.rtc = null;
|
|
411
691
|
}
|
|
412
692
|
function pc_AddTurnServer(hnd, urlPtr, usernamePtr, passwordPtr) {
|
|
413
|
-
pc_log(LOG_LEVEL_INFO, "pc_AddTurnServer: hnd="
|
|
693
|
+
pc_log(LOG_LEVEL_INFO, "pc_AddTurnServer: hnd=".concat(hnd));
|
|
414
694
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
415
695
|
if (pc == null) {
|
|
416
696
|
return;
|
|
@@ -418,7 +698,7 @@ function pc_AddTurnServer(hnd, urlPtr, usernamePtr, passwordPtr) {
|
|
|
418
698
|
var url = em_module.UTF8ToString(urlPtr);
|
|
419
699
|
var username = em_module.UTF8ToString(usernamePtr);
|
|
420
700
|
var credential = em_module.UTF8ToString(passwordPtr);
|
|
421
|
-
pc_log(LOG_LEVEL_INFO, "pc_AddTurnServer: hnd="
|
|
701
|
+
pc_log(LOG_LEVEL_INFO, "pc_AddTurnServer: hnd=".concat(hnd, " adding: ").concat(url));
|
|
422
702
|
var server = {
|
|
423
703
|
urls: url,
|
|
424
704
|
username: username,
|
|
@@ -431,15 +711,15 @@ function pc_HasVideo(hnd) {
|
|
|
431
711
|
if (pc == null) {
|
|
432
712
|
return 0;
|
|
433
713
|
}
|
|
434
|
-
pc_log(LOG_LEVEL_INFO, "pc_HasVideo("
|
|
714
|
+
pc_log(LOG_LEVEL_INFO, "pc_HasVideo(".concat(hnd, "): sending=").concat(pc.sending_video));
|
|
435
715
|
var senders = pc.rtc ? pc.rtc.getSenders() : [];
|
|
436
|
-
pc_log(
|
|
716
|
+
pc_log(LOG_LEVEL_INFO, "pc_HasVideo: " + senders.length + " senders");
|
|
437
717
|
for (var _i = 0, senders_4 = senders; _i < senders_4.length; _i++) {
|
|
438
718
|
var sender = senders_4[_i];
|
|
439
|
-
pc_log(
|
|
719
|
+
pc_log(LOG_LEVEL_INFO, "pc_HasVideo: track=" + sender.track);
|
|
440
720
|
if (sender.track) {
|
|
441
721
|
var track = sender.track;
|
|
442
|
-
pc_log(
|
|
722
|
+
pc_log(LOG_LEVEL_INFO, "pc_HasVideo: track.kind=" + track.kind + " enabled=" + track.enabled);
|
|
443
723
|
if (track.kind === 'video' && track.enabled)
|
|
444
724
|
return 1;
|
|
445
725
|
}
|
|
@@ -448,12 +728,12 @@ function pc_HasVideo(hnd) {
|
|
|
448
728
|
for (var _a = 0, txrxs_1 = txrxs; _a < txrxs_1.length; _a++) {
|
|
449
729
|
var txrx = txrxs_1[_a];
|
|
450
730
|
if (!txrx) {
|
|
451
|
-
pc_log(
|
|
731
|
+
pc_log(LOG_LEVEL_INFO, "pc_HasVideo: no txrx");
|
|
452
732
|
continue;
|
|
453
733
|
}
|
|
454
734
|
var rx = txrx.receiver;
|
|
455
735
|
var tx = txrx.sender;
|
|
456
|
-
pc_log(
|
|
736
|
+
pc_log(LOG_LEVEL_INFO, "pc_HasVideo: txrx dir=".concat(txrx.direction, "/").concat(txrx.currentDirection, " rx=").concat(rx, " tx=").concat(tx));
|
|
457
737
|
}
|
|
458
738
|
return 0;
|
|
459
739
|
}
|
|
@@ -462,7 +742,7 @@ function pc_SetVideoState(hnd, vstate) {
|
|
|
462
742
|
if (pc == null) {
|
|
463
743
|
return;
|
|
464
744
|
}
|
|
465
|
-
pc_log(LOG_LEVEL_INFO, "pc_SetVideoState: hnd="
|
|
745
|
+
pc_log(LOG_LEVEL_INFO, "pc_SetVideoState: hnd=".concat(hnd, " vstate=").concat(vstate, "/").concat(pc.vstate, " callType=").concat(pc.call_type, " active=").concat(pc.sending_video));
|
|
466
746
|
if (pc.vstate === vstate)
|
|
467
747
|
return;
|
|
468
748
|
var active = false;
|
|
@@ -487,14 +767,14 @@ function pc_SetVideoState(hnd, vstate) {
|
|
|
487
767
|
should_update = true;
|
|
488
768
|
else if (vstate === PC_VIDEO_STATE_SCREENSHARE)
|
|
489
769
|
should_update = true;
|
|
490
|
-
pc_log(
|
|
770
|
+
pc_log(LOG_LEVEL_INFO, "pc_SetVideoState: should_update=".concat(should_update, " vstate=").concat(vstate, " active=").concat(active));
|
|
491
771
|
if (should_update && userMediaHandler) {
|
|
492
772
|
var use_video = vstate === PC_VIDEO_STATE_STARTED;
|
|
493
773
|
var use_ss = vstate === PC_VIDEO_STATE_SCREENSHARE;
|
|
494
|
-
pc_log(
|
|
774
|
+
pc_log(LOG_LEVEL_INFO, "pc_SetVideoState: calling umh(1, ".concat(use_video, ", ").concat(use_ss, ")"));
|
|
495
775
|
userMediaHandler(pc.convid, true, use_video, use_ss)
|
|
496
776
|
.then(function (stream) {
|
|
497
|
-
update_tracks(pc, stream);
|
|
777
|
+
return update_tracks(pc, stream);
|
|
498
778
|
});
|
|
499
779
|
pc.sending_video = use_video || use_ss;
|
|
500
780
|
}
|
|
@@ -522,8 +802,153 @@ function sdpMap(sdp, local, bundle) {
|
|
|
522
802
|
});
|
|
523
803
|
return sdpLines.join('\r\n');
|
|
524
804
|
}
|
|
805
|
+
function sdpCbrMap(sdp) {
|
|
806
|
+
var sdpLines = [];
|
|
807
|
+
sdp.split('\r\n').forEach(function (sdpLine) {
|
|
808
|
+
var outline;
|
|
809
|
+
outline = sdpLine;
|
|
810
|
+
if (sdpLine.endsWith('sprop-stereo=0;useinbandfec=1')) {
|
|
811
|
+
outline = sdpLine + ";cbr=1";
|
|
812
|
+
}
|
|
813
|
+
else if (sdpLine.startsWith('a=ssrc-group:')) {
|
|
814
|
+
var group = sdpLine;
|
|
815
|
+
// in case of only one ssrc in group (no nack/rtx), remove attribute
|
|
816
|
+
var spaces = group.trim().split(' ').length;
|
|
817
|
+
if (spaces < 3) {
|
|
818
|
+
outline = null;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
else if (sdpLine.startsWith('a=simulcast:recv l;h') && pc_env !== ENV_FIREFOX) {
|
|
822
|
+
// add conference attribute for chrome
|
|
823
|
+
sdpLines.push('a=x-google-flag:conference');
|
|
824
|
+
}
|
|
825
|
+
// reorder rids for firefox
|
|
826
|
+
else if (sdpLine.startsWith('a=simulcast:recv l;h') && pc_env === ENV_FIREFOX) {
|
|
827
|
+
outline = 'a=simulcast:recv h;l';
|
|
828
|
+
}
|
|
829
|
+
else if (sdpLine.startsWith('a=rid:l recv') && pc_env === ENV_FIREFOX) {
|
|
830
|
+
outline = 'a=rid:h recv';
|
|
831
|
+
}
|
|
832
|
+
else if (sdpLine.startsWith('a=rid:h recv') && pc_env === ENV_FIREFOX) {
|
|
833
|
+
outline = 'a=rid:l recv';
|
|
834
|
+
}
|
|
835
|
+
if (outline != null) {
|
|
836
|
+
sdpLines.push(outline);
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
return sdpLines.join('\r\n');
|
|
840
|
+
}
|
|
841
|
+
function sdpRidReOrder(sdp) {
|
|
842
|
+
var sdpLines = [];
|
|
843
|
+
sdp.split('\r\n').forEach(function (sdpLine) {
|
|
844
|
+
var outline;
|
|
845
|
+
outline = sdpLine;
|
|
846
|
+
if (sdpLine.startsWith('a=simulcast:send h;l') && pc_env === ENV_FIREFOX) {
|
|
847
|
+
outline = 'a=simulcast:send l;h';
|
|
848
|
+
}
|
|
849
|
+
else if (sdpLine.startsWith('a=rid:h send') && pc_env === ENV_FIREFOX) {
|
|
850
|
+
outline = 'a=rid:l send';
|
|
851
|
+
}
|
|
852
|
+
else if (sdpLine.startsWith('a=rid:l send') && pc_env === ENV_FIREFOX) {
|
|
853
|
+
outline = 'a=rid:h send';
|
|
854
|
+
}
|
|
855
|
+
if (outline != null) {
|
|
856
|
+
sdpLines.push(outline);
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
return sdpLines.join('\r\n');
|
|
860
|
+
}
|
|
861
|
+
function pc_SetMediaKey(hnd, index, current, keyPtr, keyLen) {
|
|
862
|
+
var pc = connectionsStore.getPeerConnection(hnd);
|
|
863
|
+
if (pc == null) {
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
var buf = new ArrayBuffer(keyLen);
|
|
867
|
+
var ptr = new Uint8Array(em_module.HEAPU8.buffer, keyPtr, keyLen);
|
|
868
|
+
var buf8 = new Uint8Array(buf);
|
|
869
|
+
buf8.set(ptr);
|
|
870
|
+
worker.postMessage({
|
|
871
|
+
op: 'setMediaKey',
|
|
872
|
+
self: pc.self,
|
|
873
|
+
index: index,
|
|
874
|
+
current: current,
|
|
875
|
+
key: buf8
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
function pc_UpdateSsrc(hnd, ssrcaPtr, ssrcvPtr) {
|
|
879
|
+
var pc = connectionsStore.getPeerConnection(hnd);
|
|
880
|
+
if (pc == null) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
var ssrca = em_module.UTF8ToString(ssrcaPtr);
|
|
884
|
+
var ssrcv = em_module.UTF8ToString(ssrcvPtr);
|
|
885
|
+
pc_log(LOG_LEVEL_INFO, "pc_UpdateSsrc: hnd=".concat(hnd, " ssrc=").concat(ssrca, " ssrcv=").concat(ssrcv));
|
|
886
|
+
worker.postMessage({
|
|
887
|
+
op: 'updateSsrc',
|
|
888
|
+
self: pc.self,
|
|
889
|
+
ssrca: ssrca,
|
|
890
|
+
ssrcv: ssrcv
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
function setupSenderTransform(pc, sender) {
|
|
894
|
+
if (!sender || !sender.track) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
if (!insertableLegacy && !insertableStreams) {
|
|
898
|
+
pc_log(LOG_LEVEL_WARN, "setupSenderTransform: insertable streams not supported");
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
if (pc_env === ENV_FIREFOX) {
|
|
902
|
+
sender.transform = new RTCRtpScriptTransform(worker, { name: "senderTransform", self: pc.self });
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
var mtype = sender.track.kind === 'video' ? 1 : 0; // corresponds to enum frame_media_type
|
|
906
|
+
var senderStreams = null;
|
|
907
|
+
if (insertableStreams)
|
|
908
|
+
senderStreams = sender.createEncodedStreams();
|
|
909
|
+
else
|
|
910
|
+
senderStreams = mtype === 1 ? sender.createEncodedVideoStreams() : sender.createEncodedAudioStreams();
|
|
911
|
+
pc_log(LOG_LEVEL_INFO, "setupSenderTransform: senderStream: ".concat(senderStreams.readable, "/").concat(senderStreams.readableStream));
|
|
912
|
+
var readableStream = senderStreams.readable || senderStreams.readableStream;
|
|
913
|
+
var writableStream = senderStreams.writable || senderStreams.writableStream;
|
|
914
|
+
worker.postMessage({
|
|
915
|
+
op: 'setupSender',
|
|
916
|
+
self: pc.self,
|
|
917
|
+
readableStream: readableStream,
|
|
918
|
+
writableStream: writableStream,
|
|
919
|
+
}, [readableStream, writableStream]);
|
|
920
|
+
}
|
|
921
|
+
function setupReceiverTransform(pc, receiver) {
|
|
922
|
+
if (!receiver || !receiver.track) {
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
if (!insertableLegacy && !insertableStreams) {
|
|
926
|
+
pc_log(LOG_LEVEL_WARN, "setupReceiverTransform: insertable streams not supported");
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
if (pc_env == ENV_FIREFOX) {
|
|
930
|
+
receiver.transform = new RTCRtpScriptTransform(worker, { name: "receiverTransform", self: pc.self, track_id: receiver.track.id });
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
var mtype = receiver.track.kind === 'video' ? 1 : 0; // corresponds to enum frame_media_type
|
|
934
|
+
var receiverStreams = null;
|
|
935
|
+
if (insertableStreams)
|
|
936
|
+
receiverStreams = receiver.createEncodedStreams();
|
|
937
|
+
else
|
|
938
|
+
receiverStreams = mtype === 1 ? receiver.createEncodedVideoStreams() : receiver.createEncodedAudioStreams();
|
|
939
|
+
pc_log(LOG_LEVEL_INFO, "setupReceiverTransform: receiverStream: ".concat(receiverStreams.readable, "/").concat(receiverStreams.readableStream));
|
|
940
|
+
var readableStream = receiverStreams.readable || receiverStreams.readableStream;
|
|
941
|
+
var writableStream = receiverStreams.writable || receiverStreams.writableStream;
|
|
942
|
+
worker.postMessage({
|
|
943
|
+
op: 'setupReceiver',
|
|
944
|
+
self: pc.self,
|
|
945
|
+
readableStream: readableStream,
|
|
946
|
+
writableStream: writableStream,
|
|
947
|
+
}, [readableStream, writableStream]);
|
|
948
|
+
}
|
|
525
949
|
function createSdp(pc, callType, vstate, isOffer) {
|
|
526
950
|
var rtc = pc.rtc;
|
|
951
|
+
pc_log(LOG_LEVEL_INFO, "createSdp: isOffer=".concat(isOffer, " rtc=").concat(rtc));
|
|
527
952
|
if (!rtc) {
|
|
528
953
|
return;
|
|
529
954
|
}
|
|
@@ -531,12 +956,13 @@ function createSdp(pc, callType, vstate, isOffer) {
|
|
|
531
956
|
pc.vstate = vstate;
|
|
532
957
|
var use_video = vstate === PC_VIDEO_STATE_STARTED;
|
|
533
958
|
var use_ss = vstate === PC_VIDEO_STATE_SCREENSHARE;
|
|
534
|
-
pc_log(
|
|
959
|
+
pc_log(LOG_LEVEL_INFO, "createSdp: calling umh(1, ".concat(use_video, ", ").concat(use_ss, ")"));
|
|
535
960
|
pc.sending_video = use_video || use_ss;
|
|
536
961
|
if (userMediaHandler) {
|
|
537
962
|
userMediaHandler(pc.convid, true, use_video, use_ss)
|
|
538
963
|
.then(function (stream) {
|
|
539
|
-
update_tracks(pc, stream);
|
|
964
|
+
return update_tracks(pc, stream).then(function () { return stream; });
|
|
965
|
+
}).then(function (stream) {
|
|
540
966
|
var doSdp = isOffer
|
|
541
967
|
? rtc.createOffer
|
|
542
968
|
: rtc.createAnswer;
|
|
@@ -547,15 +973,17 @@ function createSdp(pc, callType, vstate, isOffer) {
|
|
|
547
973
|
.then(function (sdp) {
|
|
548
974
|
var typeStr = sdp.type;
|
|
549
975
|
var sdpStr = sdp.sdp || '';
|
|
550
|
-
pc_log(
|
|
976
|
+
pc_log(LOG_LEVEL_INFO, "createSdp: type=".concat(typeStr, " sdp=").concat(sdpStr));
|
|
551
977
|
var modSdp = sdpMap(sdpStr, true, false);
|
|
552
978
|
ccallLocalSdpHandler(pc, 0, typeStr, modSdp);
|
|
553
979
|
})
|
|
554
980
|
.catch(function (err) {
|
|
981
|
+
pc_log(LOG_LEVEL_WARN, 'createSdp: doSdp failed: ' + err, err);
|
|
555
982
|
ccallLocalSdpHandler(pc, 1, "sdp-error", err.toString());
|
|
556
983
|
});
|
|
557
984
|
})
|
|
558
985
|
.catch(function (err) {
|
|
986
|
+
pc_log(LOG_LEVEL_WARN, 'createSdp: userMedia failed: ' + err, err);
|
|
559
987
|
ccallLocalSdpHandler(pc, 1, "media-error", err.toString());
|
|
560
988
|
});
|
|
561
989
|
}
|
|
@@ -565,19 +993,115 @@ function pc_CreateOffer(hnd, callType, vstate) {
|
|
|
565
993
|
if (pc == null) {
|
|
566
994
|
return;
|
|
567
995
|
}
|
|
568
|
-
pc_log(LOG_LEVEL_INFO, "pc_CreateOffer: hnd="
|
|
996
|
+
pc_log(LOG_LEVEL_INFO, "pc_CreateOffer: hnd=".concat(hnd, " self=").concat(pc.self.toString(16), " call_type=").concat(callType));
|
|
569
997
|
createSdp(pc, callType, vstate, true);
|
|
570
998
|
}
|
|
571
999
|
function pc_CreateAnswer(hnd, callType, vstate) {
|
|
572
|
-
pc_log(LOG_LEVEL_INFO, "pc_CreateAnswer: "
|
|
1000
|
+
pc_log(LOG_LEVEL_INFO, "pc_CreateAnswer: ".concat(hnd, " callType=").concat(callType));
|
|
573
1001
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
1002
|
+
pc_log(LOG_LEVEL_INFO, 'pc_CreateAnswer: pc=' + pc);
|
|
574
1003
|
if (pc == null) {
|
|
575
1004
|
return;
|
|
576
1005
|
}
|
|
577
1006
|
createSdp(pc, callType, vstate, false);
|
|
578
1007
|
}
|
|
1008
|
+
function pc_AddDecoderAnswer(hnd) {
|
|
1009
|
+
pc_log(LOG_LEVEL_INFO, "pc_AddDecoderAnswer: ".concat(hnd));
|
|
1010
|
+
var pc = connectionsStore.getPeerConnection(hnd);
|
|
1011
|
+
pc_log(LOG_LEVEL_INFO, 'pc_AddDecoderAnswer: pc=' + pc);
|
|
1012
|
+
if (pc == null) {
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
var rtc = pc.rtc;
|
|
1016
|
+
if (!rtc)
|
|
1017
|
+
return;
|
|
1018
|
+
rtc.createAnswer().then(function (sdp) {
|
|
1019
|
+
var typeStr = sdp.type;
|
|
1020
|
+
var sdpStr = sdp.sdp || '';
|
|
1021
|
+
//pc_log(LOG_LEVEL_INFO, `createSdp: type=${typeStr} sdp=${sdpStr}`);
|
|
1022
|
+
ccallLocalSdpHandler(pc, 0, typeStr, sdpStr);
|
|
1023
|
+
})
|
|
1024
|
+
.catch(function (err) {
|
|
1025
|
+
pc_log(LOG_LEVEL_WARN, 'addDecoderAnswer: createAnswer failed: ' + err, err);
|
|
1026
|
+
ccallLocalSdpHandler(pc, 1, "sdp-error", err.toString());
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* This methode is called by the jsflow
|
|
1031
|
+
*
|
|
1032
|
+
* @see: jsflow.c::jsflow_add_decoders_for_user
|
|
1033
|
+
*/
|
|
1034
|
+
function pc_AddUserInfo(hnd, labelPtr, useridPtr, clientidPtr, ssrcaPtr, ssrcvPtr, audioIvPtr, videoIvPtr, ivlen) {
|
|
1035
|
+
pc_log(LOG_LEVEL_INFO, "pc_AddUserInfo2: hnd=".concat(hnd));
|
|
1036
|
+
var pc = connectionsStore.getPeerConnection(hnd);
|
|
1037
|
+
if (pc == null) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
var label = em_module.UTF8ToString(labelPtr);
|
|
1041
|
+
var userId = em_module.UTF8ToString(useridPtr);
|
|
1042
|
+
var clientId = em_module.UTF8ToString(clientidPtr);
|
|
1043
|
+
var ssrca = em_module.UTF8ToString(ssrcaPtr);
|
|
1044
|
+
var ssrcv = em_module.UTF8ToString(ssrcvPtr);
|
|
1045
|
+
var iva = new ArrayBuffer(ivlen);
|
|
1046
|
+
var aptr = new Uint8Array(em_module.HEAPU8.buffer, audioIvPtr, ivlen);
|
|
1047
|
+
var iva8 = new Uint8Array(iva);
|
|
1048
|
+
iva8.set(aptr);
|
|
1049
|
+
var ivv = new ArrayBuffer(ivlen);
|
|
1050
|
+
var vptr = new Uint8Array(em_module.HEAPU8.buffer, videoIvPtr, ivlen);
|
|
1051
|
+
var ivv8 = new Uint8Array(ivv);
|
|
1052
|
+
ivv8.set(vptr);
|
|
1053
|
+
var uinfo = {
|
|
1054
|
+
label: label,
|
|
1055
|
+
video_track_id: "0",
|
|
1056
|
+
userid: userId,
|
|
1057
|
+
clientid: clientId,
|
|
1058
|
+
ssrca: ssrca,
|
|
1059
|
+
ssrcv: ssrcv,
|
|
1060
|
+
iva: iva8,
|
|
1061
|
+
ivv: ivv8,
|
|
1062
|
+
frame_width: 0,
|
|
1063
|
+
frame_height: 0,
|
|
1064
|
+
audio_level: 0,
|
|
1065
|
+
first_recv_audio: false,
|
|
1066
|
+
first_succ_audio: false,
|
|
1067
|
+
first_succ_video: false,
|
|
1068
|
+
transp_ssrcv: null,
|
|
1069
|
+
};
|
|
1070
|
+
pc_log(LOG_LEVEL_INFO, "pc_AddUserInfo: label=".concat(label, " ").concat(userId.substring(0, 8), "/").concat(clientId.substring(0, 4), " ssrc:").concat(ssrca, "/").concat(ssrcv));
|
|
1071
|
+
pc.users[label] = uinfo;
|
|
1072
|
+
worker.postMessage({
|
|
1073
|
+
op: 'addUser',
|
|
1074
|
+
self: pc.self,
|
|
1075
|
+
userInfo: uinfo
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
function pc_RemoveUserInfo(hnd, labelPtr) {
|
|
1079
|
+
var label = em_module.UTF8ToString(labelPtr);
|
|
1080
|
+
pc_log(LOG_LEVEL_INFO, "pc_RemoveUserInfo: hnd=".concat(hnd, " label=").concat(label));
|
|
1081
|
+
var pc = connectionsStore.getPeerConnection(hnd);
|
|
1082
|
+
if (pc == null) {
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
if (pc.users.hasOwnProperty(label)) {
|
|
1086
|
+
if (audioStreamHandler) {
|
|
1087
|
+
pc_log(LOG_LEVEL_INFO, "pcRemoveUserInfo: calling ash(".concat(pc.convid.substring(0, 8), ", ").concat(label, ") with 0 streams"));
|
|
1088
|
+
audioStreamHandler(pc.convid, hnd.toString() + label, null);
|
|
1089
|
+
}
|
|
1090
|
+
delete pc.users[label];
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function extractSSRCs(pc, sdp) {
|
|
1094
|
+
sdp.split('\r\n').forEach(function (l) {
|
|
1095
|
+
var m = l.match(/a=ssrc:(\d+) msid:(.*) (.*)/);
|
|
1096
|
+
if (m) {
|
|
1097
|
+
var ssrc = m[1];
|
|
1098
|
+
var label = m[3];
|
|
1099
|
+
pc.streams[ssrc] = label;
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
579
1103
|
function pc_SetRemoteDescription(hnd, typePtr, sdpPtr) {
|
|
580
|
-
pc_log(LOG_LEVEL_INFO, "pc_SetRemoteDescription: hnd="
|
|
1104
|
+
pc_log(LOG_LEVEL_INFO, "pc_SetRemoteDescription: hnd=".concat(hnd));
|
|
581
1105
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
582
1106
|
if (pc == null) {
|
|
583
1107
|
return;
|
|
@@ -593,15 +1117,22 @@ function pc_SetRemoteDescription(hnd, typePtr, sdpPtr) {
|
|
|
593
1117
|
sdpStr = sdp.replace(/ DTLS\/SCTP (5000|webrtc-datachannel)/, ' UDP/DTLS/SCTP webrtc-datachannel');
|
|
594
1118
|
sdpStr = sdpMap(sdpStr, false, false);
|
|
595
1119
|
}
|
|
1120
|
+
/* Ensure that we force CBR on the offer */
|
|
1121
|
+
if (pc.conv_type == CONV_TYPE_CONFERENCE) {
|
|
1122
|
+
sdpStr = sdpCbrMap(sdpStr);
|
|
1123
|
+
}
|
|
1124
|
+
pc_log(LOG_LEVEL_INFO, "pc_SetRemoteDescription: hnd=".concat(hnd, " SDP=").concat(sdpStr));
|
|
596
1125
|
rtc
|
|
597
1126
|
.setRemoteDescription({ type: type, sdp: sdpStr })
|
|
598
1127
|
.then(function () { })
|
|
599
1128
|
.catch(function (err) {
|
|
600
|
-
pc_log(LOG_LEVEL_WARN, "setRemoteDescription failed: " + err);
|
|
1129
|
+
pc_log(LOG_LEVEL_WARN, "setRemoteDescription failed: " + err, err);
|
|
601
1130
|
});
|
|
1131
|
+
if (pc_env != ENV_FIREFOX)
|
|
1132
|
+
extractSSRCs(pc, sdp);
|
|
602
1133
|
}
|
|
603
1134
|
function pc_SetLocalDescription(hnd, typePtr, sdpPtr) {
|
|
604
|
-
pc_log(LOG_LEVEL_INFO, "pc_SetLocalDescription: hnd="
|
|
1135
|
+
pc_log(LOG_LEVEL_INFO, "pc_SetLocalDescription: hnd=".concat(hnd));
|
|
605
1136
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
606
1137
|
if (pc == null) {
|
|
607
1138
|
return;
|
|
@@ -617,59 +1148,74 @@ function pc_SetLocalDescription(hnd, typePtr, sdpPtr) {
|
|
|
617
1148
|
sdpStr = sdpMap(sdp, true, false);
|
|
618
1149
|
else
|
|
619
1150
|
sdpStr = sdp;
|
|
620
|
-
pc_log(
|
|
1151
|
+
//pc_log(LOG_LEVEL_INFO, `pc_SetLocalDesription: type=${type} sdp=${sdpStr}`);
|
|
621
1152
|
rtc
|
|
622
1153
|
.setLocalDescription({ type: type, sdp: sdpStr })
|
|
623
|
-
.then(function () {
|
|
1154
|
+
.then(function () {
|
|
1155
|
+
if (rtc && pc.conv_type === CONV_TYPE_CONFERENCE) {
|
|
1156
|
+
for (var _i = 0, _a = rtc.getSenders(); _i < _a.length; _i++) {
|
|
1157
|
+
var sender = _a[_i];
|
|
1158
|
+
setupSenderTransform(pc, sender);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
})
|
|
624
1162
|
.catch(function (err) {
|
|
625
|
-
pc_log(LOG_LEVEL_INFO, "setLocalDescription failed: " + err);
|
|
1163
|
+
pc_log(LOG_LEVEL_INFO, "setLocalDescription failed: " + err, err);
|
|
626
1164
|
});
|
|
627
1165
|
}
|
|
628
1166
|
function pc_LocalDescription(hnd, typePtr) {
|
|
629
|
-
pc_log(LOG_LEVEL_INFO, "pc_LocalDescription: hnd="
|
|
1167
|
+
pc_log(LOG_LEVEL_INFO, "pc_LocalDescription: hnd=".concat(hnd));
|
|
630
1168
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
631
1169
|
if (pc == null) {
|
|
632
|
-
return;
|
|
1170
|
+
return 0;
|
|
633
1171
|
}
|
|
634
1172
|
var rtc = pc.rtc;
|
|
635
1173
|
if (!rtc) {
|
|
636
|
-
return;
|
|
1174
|
+
return 0;
|
|
637
1175
|
}
|
|
638
1176
|
var sdpDesc = rtc.localDescription;
|
|
639
1177
|
if (!sdpDesc) {
|
|
640
|
-
return;
|
|
1178
|
+
return 0;
|
|
641
1179
|
}
|
|
642
1180
|
if (typePtr != null) {
|
|
643
1181
|
var type = em_module.UTF8ToString(typePtr);
|
|
644
1182
|
if (type != sdpDesc.type) {
|
|
645
1183
|
pc_log(LOG_LEVEL_WARN, "pc_LocalDescriptiont: wrong type");
|
|
646
|
-
return
|
|
1184
|
+
return 0;
|
|
647
1185
|
}
|
|
648
1186
|
}
|
|
649
1187
|
var sdp = sdpDesc.sdp.toString();
|
|
650
1188
|
var sdpStr = sdp;
|
|
651
|
-
pc_log(LOG_LEVEL_INFO, "pc_LocalDescription: env="
|
|
1189
|
+
pc_log(LOG_LEVEL_INFO, "pc_LocalDescription: env=".concat(pc_env));
|
|
652
1190
|
if (pc_env === ENV_FIREFOX) {
|
|
653
1191
|
sdpStr = sdp.replace(' UDP/DTLS/SCTP', ' DTLS/SCTP');
|
|
654
1192
|
sdpStr = sdpMap(sdpStr, true, false);
|
|
655
1193
|
}
|
|
1194
|
+
/* Ensure that we force CBR on the offer */
|
|
1195
|
+
if (pc_env === ENV_FIREFOX && pc.conv_type == CONV_TYPE_CONFERENCE) {
|
|
1196
|
+
sdpStr = sdpRidReOrder(sdpStr);
|
|
1197
|
+
}
|
|
1198
|
+
pc_log(LOG_LEVEL_INFO, "pc_LocalDescription: hnd=".concat(sdpStr));
|
|
656
1199
|
var sdpLen = em_module.lengthBytesUTF8(sdpStr) + 1; // +1 for '\0'
|
|
657
1200
|
var ptr = em_module._malloc(sdpLen);
|
|
658
1201
|
em_module.stringToUTF8(sdpStr, ptr, sdpLen);
|
|
659
1202
|
return ptr;
|
|
660
1203
|
}
|
|
1204
|
+
function pc_HeapFree(ptr) {
|
|
1205
|
+
em_module._free(ptr);
|
|
1206
|
+
}
|
|
661
1207
|
function pc_IceGatheringState(hnd) {
|
|
662
|
-
pc_log(LOG_LEVEL_INFO, "pc_IceGatheringState: hnd="
|
|
1208
|
+
pc_log(LOG_LEVEL_INFO, "pc_IceGatheringState: hnd=".concat(hnd));
|
|
1209
|
+
var state = PC_GATHER_STATE_UNKNOWN;
|
|
663
1210
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
664
1211
|
if (!pc) {
|
|
665
|
-
return
|
|
1212
|
+
return state;
|
|
666
1213
|
}
|
|
667
1214
|
var rtc = pc.rtc;
|
|
668
1215
|
if (!rtc) {
|
|
669
|
-
return;
|
|
1216
|
+
return state;
|
|
670
1217
|
}
|
|
671
1218
|
var stateStr = rtc.iceGatheringState;
|
|
672
|
-
var state = PC_GATHER_STATE_UNKNOWN;
|
|
673
1219
|
switch (stateStr) {
|
|
674
1220
|
case "new":
|
|
675
1221
|
state = PC_GATHER_STATE_NEW;
|
|
@@ -684,22 +1230,23 @@ function pc_IceGatheringState(hnd) {
|
|
|
684
1230
|
return state;
|
|
685
1231
|
}
|
|
686
1232
|
function pc_SignalingState(hnd) {
|
|
687
|
-
pc_log(LOG_LEVEL_INFO, "pc_SignalingState: hnd="
|
|
1233
|
+
pc_log(LOG_LEVEL_INFO, "pc_SignalingState: hnd=".concat(hnd));
|
|
1234
|
+
var state = PC_SIG_STATE_UNKNOWN;
|
|
688
1235
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
689
1236
|
if (!pc) {
|
|
690
|
-
return
|
|
1237
|
+
return state;
|
|
691
1238
|
}
|
|
692
1239
|
var rtc = pc.rtc;
|
|
693
1240
|
if (!rtc) {
|
|
694
|
-
return;
|
|
1241
|
+
return state;
|
|
695
1242
|
}
|
|
696
1243
|
var stateStr = rtc.signalingState;
|
|
697
|
-
|
|
698
|
-
pc_log(LOG_LEVEL_INFO, "pc_SignalingState: hnd="
|
|
1244
|
+
state = sigState(stateStr);
|
|
1245
|
+
pc_log(LOG_LEVEL_INFO, "pc_SignalingState: hnd=".concat(hnd, " ") + stateStr + " mapped: " + state);
|
|
699
1246
|
return state;
|
|
700
1247
|
}
|
|
701
1248
|
function pc_ConnectionState(hnd) {
|
|
702
|
-
pc_log(LOG_LEVEL_INFO, "pc_ConnectionState: hnd="
|
|
1249
|
+
pc_log(LOG_LEVEL_INFO, "pc_ConnectionState: hnd=".concat(hnd));
|
|
703
1250
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
704
1251
|
if (!pc) {
|
|
705
1252
|
return 0;
|
|
@@ -709,7 +1256,7 @@ function pc_ConnectionState(hnd) {
|
|
|
709
1256
|
*/
|
|
710
1257
|
var rtc = pc.rtc;
|
|
711
1258
|
if (!rtc) {
|
|
712
|
-
return;
|
|
1259
|
+
return 0;
|
|
713
1260
|
}
|
|
714
1261
|
var state = rtc.connectionState;
|
|
715
1262
|
return state;
|
|
@@ -725,7 +1272,7 @@ function pc_SetMute(hnd, muted) {
|
|
|
725
1272
|
function pc_GetMute(hnd) {
|
|
726
1273
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
727
1274
|
if (pc == null) {
|
|
728
|
-
return;
|
|
1275
|
+
return 0;
|
|
729
1276
|
}
|
|
730
1277
|
return pc.muted;
|
|
731
1278
|
}
|
|
@@ -739,14 +1286,14 @@ function pc_SetRemoteUserClientId(hnd, useridPtr, clientidPtr) {
|
|
|
739
1286
|
}
|
|
740
1287
|
/* Data Channel related */
|
|
741
1288
|
function pc_CreateDataChannel(hnd, labelPtr) {
|
|
742
|
-
pc_log(LOG_LEVEL_INFO, "pc_CreateDataChannel: hnd="
|
|
1289
|
+
pc_log(LOG_LEVEL_INFO, "pc_CreateDataChannel: hnd=".concat(hnd));
|
|
743
1290
|
var pc = connectionsStore.getPeerConnection(hnd);
|
|
744
1291
|
if (pc == null) {
|
|
745
|
-
return;
|
|
1292
|
+
return 0;
|
|
746
1293
|
}
|
|
747
1294
|
var rtc = pc.rtc;
|
|
748
1295
|
if (!rtc) {
|
|
749
|
-
return;
|
|
1296
|
+
return 0;
|
|
750
1297
|
}
|
|
751
1298
|
var label = em_module.UTF8ToString(labelPtr);
|
|
752
1299
|
var dc = rtc.createDataChannel(label);
|
|
@@ -757,7 +1304,7 @@ function pc_CreateDataChannel(hnd, labelPtr) {
|
|
|
757
1304
|
return dcHnd;
|
|
758
1305
|
}
|
|
759
1306
|
function pc_DataChannelId(hnd) {
|
|
760
|
-
pc_log(LOG_LEVEL_INFO, "pc_DataChannelId: hnd="
|
|
1307
|
+
pc_log(LOG_LEVEL_INFO, "pc_DataChannelId: hnd=".concat(hnd));
|
|
761
1308
|
var dc = connectionsStore.getDataChannel(hnd);
|
|
762
1309
|
if (dc == null) {
|
|
763
1310
|
return -1;
|
|
@@ -765,13 +1312,13 @@ function pc_DataChannelId(hnd) {
|
|
|
765
1312
|
return dc.id;
|
|
766
1313
|
}
|
|
767
1314
|
function pc_DataChannelState(hnd) {
|
|
768
|
-
pc_log(LOG_LEVEL_INFO, "pc_DataChannelState: hnd="
|
|
1315
|
+
pc_log(LOG_LEVEL_INFO, "pc_DataChannelState: hnd=".concat(hnd));
|
|
1316
|
+
var state = DC_STATE_ERROR;
|
|
769
1317
|
var dc = connectionsStore.getDataChannel(hnd);
|
|
770
1318
|
if (dc == null) {
|
|
771
|
-
return;
|
|
1319
|
+
return state;
|
|
772
1320
|
}
|
|
773
1321
|
var str = dc.readyState;
|
|
774
|
-
var state = DC_STATE_ERROR;
|
|
775
1322
|
if (str == "connecting") {
|
|
776
1323
|
state = DC_STATE_CONNECTING;
|
|
777
1324
|
}
|
|
@@ -787,13 +1334,13 @@ function pc_DataChannelState(hnd) {
|
|
|
787
1334
|
return state;
|
|
788
1335
|
}
|
|
789
1336
|
function pc_DataChannelSend(hnd, dataPtr, dataLen) {
|
|
790
|
-
pc_log(LOG_LEVEL_INFO, "pc_DataChannelSend: hnd="
|
|
1337
|
+
pc_log(LOG_LEVEL_INFO, "pc_DataChannelSend: hnd=".concat(hnd));
|
|
791
1338
|
var dc = connectionsStore.getDataChannel(hnd);
|
|
792
1339
|
if (dc == null) {
|
|
793
1340
|
return;
|
|
794
1341
|
}
|
|
795
1342
|
if (dc.readyState !== 'open') {
|
|
796
|
-
pc_log(LOG_LEVEL_WARN, "pc_DataChannelSend: hnd="
|
|
1343
|
+
pc_log(LOG_LEVEL_WARN, "pc_DataChannelSend: hnd=".concat(hnd, " not open"));
|
|
797
1344
|
return;
|
|
798
1345
|
}
|
|
799
1346
|
//const data = new Uint8Array(em_module.HEAPU8.buffer, dataPtr, dataLen);
|
|
@@ -801,7 +1348,7 @@ function pc_DataChannelSend(hnd, dataPtr, dataLen) {
|
|
|
801
1348
|
dc.send(data);
|
|
802
1349
|
}
|
|
803
1350
|
function pc_DataChannelClose(hnd) {
|
|
804
|
-
pc_log(LOG_LEVEL_INFO, "pc_DataChannelClose: hnd="
|
|
1351
|
+
pc_log(LOG_LEVEL_INFO, "pc_DataChannelClose: hnd=".concat(hnd));
|
|
805
1352
|
var dc = connectionsStore.getDataChannel(hnd);
|
|
806
1353
|
if (dc == null) {
|
|
807
1354
|
return;
|
|
@@ -810,33 +1357,44 @@ function pc_DataChannelClose(hnd) {
|
|
|
810
1357
|
}
|
|
811
1358
|
/* Internal functions, used by avs_wcall directly */
|
|
812
1359
|
function pc_InitModule(module, logh) {
|
|
1360
|
+
createWorker();
|
|
813
1361
|
em_module = module;
|
|
814
1362
|
logFn = logh;
|
|
815
|
-
|
|
1363
|
+
var pt = RTCRtpSender.prototype;
|
|
1364
|
+
insertableStreams = !!pt.createEncodedStreams || "transform" in pt;
|
|
1365
|
+
insertableLegacy = !!pt.createEncodedVideoStreams;
|
|
1366
|
+
pc_log(LOG_LEVEL_INFO, "insertable: ".concat(insertableLegacy, "/").concat(insertableStreams));
|
|
816
1367
|
var callbacks = [
|
|
817
|
-
[pc_SetEnv, "
|
|
818
|
-
[pc_New, "
|
|
819
|
-
[pc_Create, "
|
|
820
|
-
[pc_Close, "
|
|
821
|
-
[
|
|
822
|
-
[
|
|
823
|
-
[
|
|
824
|
-
[
|
|
825
|
-
[
|
|
826
|
-
[
|
|
827
|
-
[
|
|
828
|
-
[
|
|
829
|
-
[
|
|
830
|
-
[
|
|
831
|
-
[
|
|
832
|
-
[
|
|
833
|
-
[
|
|
834
|
-
[
|
|
835
|
-
[
|
|
836
|
-
[
|
|
837
|
-
[
|
|
838
|
-
[
|
|
839
|
-
[
|
|
1368
|
+
[pc_SetEnv, "vi"],
|
|
1369
|
+
[pc_New, "iiiiii"],
|
|
1370
|
+
[pc_Create, "viii"],
|
|
1371
|
+
[pc_Close, "vi"],
|
|
1372
|
+
[pc_HeapFree, "vi"],
|
|
1373
|
+
[pc_AddTurnServer, "viiii"],
|
|
1374
|
+
[pc_IceGatheringState, "ii"],
|
|
1375
|
+
[pc_SignalingState, "ii"],
|
|
1376
|
+
[pc_ConnectionState, "ii"],
|
|
1377
|
+
[pc_CreateDataChannel, "iii"],
|
|
1378
|
+
[pc_CreateOffer, "viii"],
|
|
1379
|
+
[pc_CreateAnswer, "viii"],
|
|
1380
|
+
[pc_AddDecoderAnswer, "vi"],
|
|
1381
|
+
[pc_AddUserInfo, "viiiiiiiii"],
|
|
1382
|
+
[pc_RemoveUserInfo, "vii"],
|
|
1383
|
+
[pc_SetRemoteDescription, "viii"],
|
|
1384
|
+
[pc_SetLocalDescription, "viii"],
|
|
1385
|
+
[pc_LocalDescription, "iii"],
|
|
1386
|
+
[pc_SetMute, "vii"],
|
|
1387
|
+
[pc_GetMute, "ii"],
|
|
1388
|
+
[pc_GetLocalStats, "vi"],
|
|
1389
|
+
[pc_SetRemoteUserClientId, "viii"],
|
|
1390
|
+
[pc_HasVideo, "ii"],
|
|
1391
|
+
[pc_SetVideoState, "vii"],
|
|
1392
|
+
[pc_DataChannelId, "ii"],
|
|
1393
|
+
[pc_DataChannelState, "ii"],
|
|
1394
|
+
[pc_DataChannelSend, "viii"],
|
|
1395
|
+
[pc_DataChannelClose, "vi"],
|
|
1396
|
+
[pc_SetMediaKey, "viiiii"],
|
|
1397
|
+
[pc_UpdateSsrc, "viii"],
|
|
840
1398
|
].map(function (_a) {
|
|
841
1399
|
var callback = _a[0], signature = _a[1];
|
|
842
1400
|
return em_module.addFunction(callback, signature);
|
|
@@ -846,8 +1404,14 @@ function pc_InitModule(module, logh) {
|
|
|
846
1404
|
function pc_SetUserMediaHandler(umh) {
|
|
847
1405
|
userMediaHandler = umh;
|
|
848
1406
|
}
|
|
849
|
-
function
|
|
850
|
-
|
|
1407
|
+
function pc_IsConferenceCallingSupported() {
|
|
1408
|
+
return insertableStreams || insertableLegacy;
|
|
1409
|
+
}
|
|
1410
|
+
function pc_SetAudioStreamHandler(ash) {
|
|
1411
|
+
audioStreamHandler = ash;
|
|
1412
|
+
}
|
|
1413
|
+
function pc_SetVideoStreamHandler(vsh) {
|
|
1414
|
+
videoStreamHandler = vsh;
|
|
851
1415
|
}
|
|
852
1416
|
function pc_ReplaceTrack(convid, newTrack) {
|
|
853
1417
|
var pcs = connectionsStore.getPeerConnectionByConvid(convid);
|
|
@@ -864,21 +1428,127 @@ function pc_ReplaceTrack(convid, newTrack) {
|
|
|
864
1428
|
function pc_GetStats(convid) {
|
|
865
1429
|
var pcs = connectionsStore.getPeerConnectionByConvid(convid);
|
|
866
1430
|
var statsPromises = [];
|
|
867
|
-
var
|
|
1431
|
+
var _loop_3 = function (pc) {
|
|
868
1432
|
var rtc = pc.rtc;
|
|
869
1433
|
if (rtc)
|
|
870
1434
|
statsPromises.push(rtc.getStats().then(function (stats) { return ({ userid: pc.remote_userid, stats: stats }); }));
|
|
871
1435
|
};
|
|
872
1436
|
for (var _i = 0, pcs_2 = pcs; _i < pcs_2.length; _i++) {
|
|
873
1437
|
var pc = pcs_2[_i];
|
|
874
|
-
|
|
1438
|
+
_loop_3(pc);
|
|
875
1439
|
}
|
|
876
1440
|
return Promise.all(statsPromises);
|
|
877
1441
|
}
|
|
1442
|
+
function pc_GetLocalStats(hnd) {
|
|
1443
|
+
pc_log(LOG_LEVEL_INFO, "pc_GetLocalStats: hnd=".concat(hnd));
|
|
1444
|
+
var pc = connectionsStore.getPeerConnection(hnd);
|
|
1445
|
+
if (pc == null) {
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
var rtc = pc.rtc;
|
|
1449
|
+
if (!rtc) {
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
var txrxs = rtc.getTransceivers();
|
|
1453
|
+
txrxs.forEach(function (txrx) {
|
|
1454
|
+
var rx = txrx.receiver;
|
|
1455
|
+
if (rx) {
|
|
1456
|
+
var ssrcs = rx.getSynchronizationSources();
|
|
1457
|
+
ssrcs.forEach(function (ssrc) {
|
|
1458
|
+
var ssrca = "";
|
|
1459
|
+
var aulevel = 0;
|
|
1460
|
+
if (typeof ssrc.audioLevel !== 'undefined')
|
|
1461
|
+
aulevel = ((ssrc.audioLevel * 512.0) | 0);
|
|
1462
|
+
if (pc.conv_type != CONV_TYPE_ONEONONE) {
|
|
1463
|
+
var uinfo = uinfo_from_ssrca(pc, ssrc.source.toString());
|
|
1464
|
+
if (uinfo) {
|
|
1465
|
+
uinfo.audio_level = aulevel;
|
|
1466
|
+
ssrca = uinfo.ssrca;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
em_module.ccall("pc_set_audio_level", null, ["number", "number", "number"], [pc.self, ssrca, aulevel]);
|
|
1470
|
+
});
|
|
1471
|
+
var csrcs = rx.getContributingSources();
|
|
1472
|
+
csrcs.forEach(function (csrc) {
|
|
1473
|
+
var uinfo = uinfo_from_ssrca(pc, csrc.source.toString());
|
|
1474
|
+
if (uinfo) {
|
|
1475
|
+
uinfo.audio_level = 0;
|
|
1476
|
+
if (typeof csrc.audioLevel !== 'undefined')
|
|
1477
|
+
uinfo.audio_level = ((csrc.audioLevel * 512.0) | 0);
|
|
1478
|
+
em_module.ccall("pc_set_audio_level", null, ["number", "number", "number"], [pc.self, uinfo.ssrca, uinfo.audio_level]);
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
});
|
|
1483
|
+
var self_audio_level = 0;
|
|
1484
|
+
var apkts = 0;
|
|
1485
|
+
var vpkts = 0;
|
|
1486
|
+
var ploss = 0;
|
|
1487
|
+
rtc.getStats()
|
|
1488
|
+
.then(function (stats) {
|
|
1489
|
+
var rtt = 0;
|
|
1490
|
+
stats.forEach(function (stat) {
|
|
1491
|
+
if (stat.type === 'inbound-rtp') {
|
|
1492
|
+
ploss = ploss + stat.packetsLost;
|
|
1493
|
+
var p = stat.packetsReceived;
|
|
1494
|
+
if (stat.kind === 'audio') {
|
|
1495
|
+
apkts = apkts + p;
|
|
1496
|
+
}
|
|
1497
|
+
else if (stat.kind === 'video') {
|
|
1498
|
+
var user_info = null;
|
|
1499
|
+
if (!!stat.trackIdentifier) {
|
|
1500
|
+
user_info = uinfo_from_video_track_id(pc, stat.trackIdentifier);
|
|
1501
|
+
}
|
|
1502
|
+
if (user_info !== null) {
|
|
1503
|
+
var frame_height = !!stat.frameHeight ? stat === null || stat === void 0 ? void 0 : stat.frameHeight : 0;
|
|
1504
|
+
var frame_width = !!stat.frameWidth ? stat === null || stat === void 0 ? void 0 : stat.frameWidth : 0;
|
|
1505
|
+
if (user_info.frame_width !== frame_width || user_info.frame_height !== frame_height) {
|
|
1506
|
+
user_info.frame_width = frame_width;
|
|
1507
|
+
user_info.frame_height = frame_height;
|
|
1508
|
+
pc_log(LOG_LEVEL_INFO, "pc_user_resolution: label=".concat(user_info.label, " ").concat(user_info.userid.substring(0, 8), "/").concat(user_info.clientid.substring(0, 4), " resolution:").concat(user_info.frame_width, "x").concat(user_info.frame_height));
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
vpkts = vpkts + p;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
else if (stat.type === 'outbound-rtp') {
|
|
1515
|
+
var p = stat.packetsSent;
|
|
1516
|
+
if (stat.kind === 'audio') {
|
|
1517
|
+
pc.stats.sent_apkts = p;
|
|
1518
|
+
}
|
|
1519
|
+
else if (stat.kind === 'video') {
|
|
1520
|
+
pc.stats.sent_vpkts = p;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
else if (stat.type === 'candidate-pair') {
|
|
1524
|
+
rtt = stat.currentRoundTripTime * 1000;
|
|
1525
|
+
}
|
|
1526
|
+
else if (stat.type === 'media-source') {
|
|
1527
|
+
if (stat.kind === 'audio')
|
|
1528
|
+
self_audio_level = stat.audioLevel ? ((stat.audioLevel * 512.0) | 0) : 0;
|
|
1529
|
+
}
|
|
1530
|
+
});
|
|
1531
|
+
pc.stats.recv_apkts = apkts;
|
|
1532
|
+
pc.stats.recv_vpkts = vpkts;
|
|
1533
|
+
pc.stats.ploss = ploss - pc.stats.lastploss;
|
|
1534
|
+
pc.stats.lastploss = ploss;
|
|
1535
|
+
em_module.ccall("pc_set_stats", null, ["number", "number", "number", "number", "number", "number", "number", "number"], [
|
|
1536
|
+
pc.self, self_audio_level,
|
|
1537
|
+
pc.stats.recv_apkts,
|
|
1538
|
+
pc.stats.recv_vpkts,
|
|
1539
|
+
pc.stats.sent_apkts,
|
|
1540
|
+
pc.stats.sent_vpkts,
|
|
1541
|
+
pc.stats.ploss,
|
|
1542
|
+
rtt
|
|
1543
|
+
]);
|
|
1544
|
+
}).catch(function (err) { return pc_log(LOG_LEVEL_INFO, "pc_GetLocalStats: failed hnd=".concat(hnd, " err=").concat(err), err); });
|
|
1545
|
+
}
|
|
878
1546
|
exports.default = {
|
|
879
1547
|
init: pc_InitModule,
|
|
880
1548
|
setUserMediaHandler: pc_SetUserMediaHandler,
|
|
881
|
-
|
|
1549
|
+
setAudioStreamHandler: pc_SetAudioStreamHandler,
|
|
1550
|
+
setVideoStreamHandler: pc_SetVideoStreamHandler,
|
|
1551
|
+
isConferenceCallingSupported: pc_IsConferenceCallingSupported,
|
|
882
1552
|
replaceTrack: pc_ReplaceTrack,
|
|
883
1553
|
getStats: pc_GetStats
|
|
884
1554
|
};
|