@ylink-sdk/mobile-web 0.1.9-beta.1 → 0.1.9-beta.4

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.
Files changed (55) hide show
  1. package/dist/style.css +1 -1
  2. package/dist/ylink-sdk-mobile.umd.js +70 -70
  3. package/package.json +1 -1
  4. package/dist/e30037b8/VERSION +0 -6
  5. package/dist/e30037b8/libipvp-simd.d.ts +0 -474
  6. package/dist/e30037b8/libipvp-simd.js +0 -3267
  7. package/dist/e30037b8/libipvp-simd.prod.d.ts +0 -474
  8. package/dist/e30037b8/libipvp-simd.prod.js +0 -184
  9. package/dist/e30037b8/libipvp-simd.prod.wasm +0 -0
  10. package/dist/e30037b8/libipvp-simd.wasm +0 -0
  11. package/dist/e30037b8/libipvp.d.ts +0 -474
  12. package/dist/e30037b8/libipvp.js +0 -3267
  13. package/dist/e30037b8/libipvp.prod.d.ts +0 -474
  14. package/dist/e30037b8/libipvp.prod.js +0 -184
  15. package/dist/e30037b8/libipvp.prod.wasm +0 -0
  16. package/dist/e30037b8/libipvp.wasm +0 -0
  17. package/dist/e30037b8/librtc.d.ts +0 -438
  18. package/dist/e30037b8/librtc.global.js +0 -5863
  19. package/dist/e30037b8/librtc.global.prod.js +0 -15
  20. package/dist/e30037b8/libsfu-simd.d.ts +0 -767
  21. package/dist/e30037b8/libsfu-simd.js +0 -4822
  22. package/dist/e30037b8/libsfu-simd.prod.d.ts +0 -767
  23. package/dist/e30037b8/libsfu-simd.prod.js +0 -209
  24. package/dist/e30037b8/libsfu-simd.prod.wasm +0 -0
  25. package/dist/e30037b8/libsfu-simd.wasm +0 -0
  26. package/dist/e30037b8/libsfu.d.ts +0 -767
  27. package/dist/e30037b8/libsfu.js +0 -4822
  28. package/dist/e30037b8/libsfu.prod.d.ts +0 -767
  29. package/dist/e30037b8/libsfu.prod.js +0 -209
  30. package/dist/e30037b8/libsfu.prod.wasm +0 -0
  31. package/dist/e30037b8/libsfu.wasm +0 -0
  32. package/dist/e30037b8/libsvc-simd-m1.d.ts +0 -767
  33. package/dist/e30037b8/libsvc-simd-m1.js +0 -4921
  34. package/dist/e30037b8/libsvc-simd-m1.prod.d.ts +0 -767
  35. package/dist/e30037b8/libsvc-simd-m1.prod.js +0 -209
  36. package/dist/e30037b8/libsvc-simd-m1.prod.wasm +0 -0
  37. package/dist/e30037b8/libsvc-simd-m1.wasm +0 -0
  38. package/dist/e30037b8/libsvc-simd.d.ts +0 -767
  39. package/dist/e30037b8/libsvc-simd.js +0 -4857
  40. package/dist/e30037b8/libsvc-simd.prod.d.ts +0 -767
  41. package/dist/e30037b8/libsvc-simd.prod.js +0 -209
  42. package/dist/e30037b8/libsvc-simd.prod.wasm +0 -0
  43. package/dist/e30037b8/libsvc-simd.wasm +0 -0
  44. package/dist/e30037b8/libsvc.d.ts +0 -767
  45. package/dist/e30037b8/libsvc.js +0 -4857
  46. package/dist/e30037b8/libsvc.prod.d.ts +0 -767
  47. package/dist/e30037b8/libsvc.prod.js +0 -209
  48. package/dist/e30037b8/libsvc.prod.wasm +0 -0
  49. package/dist/e30037b8/libsvc.wasm +0 -0
  50. package/dist/e30037b8/native-audio-worker.global.js +0 -1583
  51. package/dist/e30037b8/native-audio-worker.global.prod.js +0 -15
  52. package/dist/e30037b8/native-video-worker.global.js +0 -1960
  53. package/dist/e30037b8/native-video-worker.global.prod.js +0 -15
  54. package/dist/e30037b8/worklet-audio-worker.global.js +0 -900
  55. package/dist/e30037b8/worklet-audio-worker.global.prod.js +0 -15
@@ -1,1960 +0,0 @@
1
- (function () {
2
- 'use strict';
3
-
4
- /*! *****************************************************************************
5
- Copyright (c) Microsoft Corporation.
6
-
7
- Permission to use, copy, modify, and/or distribute this software for any
8
- purpose with or without fee is hereby granted.
9
-
10
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16
- PERFORMANCE OF THIS SOFTWARE.
17
- ***************************************************************************** */
18
-
19
- function __awaiter(thisArg, _arguments, P, generator) {
20
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
21
- return new (P || (P = Promise))(function (resolve, reject) {
22
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
23
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
24
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
25
- step((generator = generator.apply(thisArg, _arguments || [])).next());
26
- });
27
- }
28
-
29
- function pipeline(middleware) {
30
- return (context, next) => {
31
- // last called middleware
32
- let index = -1;
33
- const run = (i) => __awaiter(this, void 0, void 0, function* () {
34
- if (i <= index) {
35
- console.warn('next() called multiple times');
36
- return;
37
- }
38
- index = i;
39
- let callback = middleware[i];
40
- if (i === middleware.length)
41
- callback = next;
42
- if (!callback)
43
- return;
44
- if (callback.length > 1) {
45
- return callback(context, dispatch);
46
- }
47
- yield callback(context, dispatch);
48
- return dispatch();
49
- });
50
- const dispatch = () => run(index + 1);
51
- return dispatch();
52
- };
53
- }
54
-
55
- class MojoReceiver {
56
- constructor(channel, pipe) {
57
- this.middleware = [];
58
- this.pipe = pipe || Math.random().toString(36).slice(3);
59
- this.channel = channel;
60
- }
61
- get valid() {
62
- return this.channel.has(this.pipe);
63
- }
64
- implement(key, invoke) {
65
- const m = (ctx, next) => __awaiter(this, void 0, void 0, function* () {
66
- const { method, params, status, required, attached = {} } = ctx.data;
67
- if (key !== method) {
68
- return next();
69
- }
70
- let handled = false;
71
- const transfer = [];
72
- const reAttached = {};
73
- const done = (payload) => {
74
- if (handled) {
75
- console.warn(`receiver[${this}] - ${method} reply multiple times`);
76
- return;
77
- }
78
- handled = true;
79
- this.channel.send(Object.assign(Object.assign(Object.assign({}, ctx.data), {
80
- // override params as it may contains un-cloned object
81
- params: undefined,
82
- // override attached as it may contains un-cloned object
83
- attached: reAttached }), payload), transfer);
84
- };
85
- const reply = {
86
- transfer: (...args) => {
87
- if (required) {
88
- transfer.push(...args);
89
- }
90
- return reply;
91
- },
92
- resolve: (value) => {
93
- if (!required) {
94
- handled = true;
95
- return;
96
- }
97
- done({ resolve: value, status: status + 1 });
98
- },
99
- reject: (reason) => {
100
- if (!required) {
101
- handled = true;
102
- return;
103
- }
104
- done({ status: status - 1, reject: reason });
105
- },
106
- // attached
107
- set: (key, val) => {
108
- if (required) {
109
- reAttached[key] = val;
110
- }
111
- return reply;
112
- },
113
- get: (key) => attached[key],
114
- };
115
- try {
116
- const timestamp = Date.now();
117
- yield invoke(reply, params, ctx.ports);
118
- if (true) {
119
- const delta = Date.now() - timestamp;
120
- if (delta > 100) {
121
- console.log(`receiver[${this}] - ${method}() took ${delta}ms`);
122
- }
123
- }
124
- }
125
- catch (error) {
126
- console.warn(error);
127
- if (!handled) {
128
- reply.reject(`${error}`);
129
- }
130
- }
131
- ctx.data.touched = true;
132
- if (!handled) {
133
- yield next();
134
- }
135
- });
136
- this.middleware.unshift(m);
137
- const unload = () => {
138
- const index = this.middleware.findIndex((v) => v === m);
139
- if (~index) {
140
- this.middleware.splice(index, 1);
141
- }
142
- };
143
- return unload;
144
- }
145
- reject(msg = '') {
146
- this.channel.reject(this, msg);
147
- }
148
- as() {
149
- return this;
150
- }
151
- callback() {
152
- return (ctx, next) => __awaiter(this, void 0, void 0, function* () {
153
- const { pipe, status } = ctx.data;
154
- if (pipe !== this.pipe) {
155
- return next();
156
- }
157
- if (status) {
158
- return next();
159
- }
160
- return pipeline(this.middleware)(ctx, next);
161
- });
162
- }
163
- toString() {
164
- return `${this.pipe}`;
165
- }
166
- }
167
-
168
- class MojoRemote {
169
- constructor(channel, pipe) {
170
- this.sequence = 0;
171
- this.pendings = new Map();
172
- this.pipe = pipe || Math.random().toString(36).slice(3);
173
- this.channel = channel;
174
- this.accepted = defer();
175
- }
176
- get ready() {
177
- return this.accepted.promise;
178
- }
179
- get valid() {
180
- return this.channel.has(this.pipe);
181
- }
182
- make(key) {
183
- const transfer = [];
184
- const attached = {};
185
- const ready = (params) => __awaiter(this, void 0, void 0, function* () {
186
- try {
187
- yield this.ready;
188
- }
189
- catch (error) {
190
- console.warn(`remote[${this}] - ${key}(${params}) failed with '${error}'`);
191
- throw error;
192
- }
193
- });
194
- const send = (params, required) => {
195
- this.channel.send({
196
- pipe: this.pipe,
197
- sequence: ++this.sequence,
198
- timestamp: Date.now(),
199
- method: key,
200
- status: 0,
201
- params,
202
- required,
203
- attached,
204
- }, transfer);
205
- };
206
- const invoke = {
207
- transfer: (...args) => {
208
- transfer.push(...args);
209
- return invoke;
210
- },
211
- post: (...params) => __awaiter(this, void 0, void 0, function* () {
212
- yield ready(params);
213
- send(params);
214
- }),
215
- invoke: (...params) => __awaiter(this, void 0, void 0, function* () {
216
- yield ready(params);
217
- send(params, true);
218
- const d = defer();
219
- this.pendings.set(this.sequence, d);
220
- return d.promise;
221
- }),
222
- // attached
223
- set: (key, val) => {
224
- attached[key] = val;
225
- return invoke;
226
- },
227
- get: (key) => attached[key],
228
- };
229
- return invoke;
230
- }
231
- break(msg = '') {
232
- this.channel.break(this, msg);
233
- this.pendings.forEach((p) => p.reject('broken'));
234
- this.pendings.clear();
235
- this.accepted.reject('broken');
236
- // eslint-disable-next-line prefer-promise-reject-errors
237
- this.accepted.promise = Promise.reject('broken');
238
- // handle uncaught promise
239
- this.accepted.promise.catch(NOOP);
240
- }
241
- callback() {
242
- return (ctx, next) => __awaiter(this, void 0, void 0, function* () {
243
- const { pipe, sequence, timestamp, method, status, reject, resolve } = ctx.data;
244
- if (pipe !== this.pipe) {
245
- return next();
246
- }
247
- if (!status) {
248
- return next();
249
- }
250
- const d = this.pendings.get(sequence);
251
- if (!d) {
252
- console.log(`remote[${this}] - receive unknown ${method} reply`);
253
- return;
254
- }
255
- if (status < 0) {
256
- d.reject(reject);
257
- }
258
- else {
259
- d.resolve(resolve);
260
- }
261
- this.pendings.delete(sequence);
262
- {
263
- const delta = Date.now() - timestamp;
264
- if (delta > 100) {
265
- console.log(`remote[${this}] - ${method}() took ${delta}ms`);
266
- }
267
- }
268
- });
269
- }
270
- toString() {
271
- return `${this.pipe}`;
272
- }
273
- }
274
- function defer() {
275
- const until = {};
276
- until.promise = new Promise((resolve, reject) => {
277
- until.resolve = resolve;
278
- until.reject = reject;
279
- });
280
- // handle uncaught promise
281
- until.promise.catch(NOOP);
282
- if ( typeof setTimeout !== 'undefined') {
283
- setTimeout(() => until.reject('timeout'), 10000);
284
- }
285
- return until;
286
- }
287
- const NOOP = () => {
288
- // nothing
289
- };
290
-
291
- class MojoChannel {
292
- // fix me
293
- // incompatible onmessage ev type
294
- constructor(transport) {
295
- this.remotes = new Map();
296
- this.receivers = new Map();
297
- this.pendingReceivers = new Set();
298
- const previous = transport.onmessage;
299
- this.transport = transport;
300
- this.transport.onmessage = (ev) => {
301
- const { data, ports = [] } = ev;
302
- if (isString(data)) {
303
- if (/^mojo/.test(data)) {
304
- const [, pipe] = data.split(':');
305
- const receiver = this.receivers.get(`${pipe}`);
306
- if (receiver) {
307
- this.send(`accept:${receiver}`);
308
- this.oninvitation && this.oninvitation(pipe, receiver);
309
- receiver.onready && receiver.onready();
310
- return;
311
- }
312
- this.pendingReceivers.add(pipe);
313
- this.oninvitation && this.oninvitation(pipe);
314
- if (this.pendingReceivers.has(pipe)) {
315
- previous && previous.call(this.transport, ev);
316
- }
317
- return;
318
- }
319
- if (/^accept/.test(data)) {
320
- const [, pipe] = data.split(':');
321
- const remote = this.remotes.get(pipe);
322
- if (!remote) {
323
- console.log(`unknown accept:\n${data}`);
324
- return;
325
- }
326
- remote.accepted.resolve();
327
- remote.onaccept && remote.onaccept();
328
- return;
329
- }
330
- if (/^reject/.test(data)) {
331
- const [, pipe, msg = 'rejected'] = data.split(':');
332
- const remote = this.remotes.get(pipe);
333
- if (!remote) {
334
- console.log(`unknown reject:\n${data}`);
335
- return;
336
- }
337
- this.remotes.delete(pipe);
338
- remote.accepted.reject(msg);
339
- remote.onreject && remote.onreject(msg);
340
- return;
341
- }
342
- if (/^break/.test(data)) {
343
- const [, pipe, msg = 'breaked'] = data.split(':');
344
- if (this.pendingReceivers.has(pipe)) {
345
- this.pendingReceivers.delete(pipe);
346
- return;
347
- }
348
- const receiver = this.receivers.get(pipe);
349
- if (!receiver) {
350
- console.log(`unknown break:\n${data}`);
351
- return;
352
- }
353
- this.receivers.delete(pipe);
354
- receiver.onbreak && receiver.onbreak(msg);
355
- return;
356
- }
357
- if (previous) {
358
- previous.call(this.transport, ev);
359
- return;
360
- }
361
- console.log(`unknown invitation:\n${data}`);
362
- return;
363
- }
364
- const ctx = { data, ports };
365
- pipeline([
366
- ...Array.from(this.remotes.values()).map((p) => p.callback()),
367
- ...Array.from(this.receivers.values()).map((p) => p.callback()),
368
- ])(ctx, () => {
369
- if (previous) {
370
- previous.call(this.transport, ev);
371
- return;
372
- }
373
- if (data.touched) {
374
-
375
- console.log(`unhandled method: ${data.pipe}::${data.method}\n` +
376
- `forget to call resolve() or reject() in method implement?`);
377
- return;
378
- }
379
- console.log('unknown message', data);
380
- });
381
- };
382
- }
383
- fork() {
384
- return new MojoChannel(this.transport);
385
- }
386
- has(pipe) {
387
- return this.remotes.has(pipe) || this.receivers.has(pipe);
388
- }
389
- close() {
390
- this.remotes.forEach((v) => v.break());
391
- this.remotes.clear();
392
- this.receivers.forEach((v) => v.reject());
393
- this.receivers.clear();
394
- this.transport.onmessage = null;
395
- this.transport = null;
396
- }
397
- send(msg, transfer) {
398
- this.transport.postMessage(msg, transfer);
399
- }
400
- reject(receiver, msg = '') {
401
- this.send(`reject:${receiver}:${msg}`);
402
- this.receivers.delete(`${receiver}`);
403
- }
404
- break(remote, msg = '') {
405
- if (!this.remotes.has(`${remote}`))
406
- return;
407
- this.send(`break:${remote}:${msg}`);
408
- this.remotes.delete(`${remote}`);
409
- }
410
- remote(pipe) {
411
- const remote = new MojoRemote(this, pipe && `${pipe}`);
412
- this.remotes.set(`${remote}`, remote);
413
- this.send(`mojo:${remote}`);
414
- return remote;
415
- }
416
- receiver(pipe) {
417
- if (pipe && this.receivers.has(`${pipe}`)) {
418
- console.log(`duplicate pipe: ${pipe}`);
419
- }
420
- const receiver = new MojoReceiver(this, pipe && `${pipe}`);
421
- this.receivers.set(`${receiver}`, receiver);
422
- if (this.pendingReceivers.has(`${receiver}`)) {
423
- this.send(`accept:${receiver}`);
424
- this.pendingReceivers.delete(`${receiver}`);
425
- receiver.onready && receiver.onready();
426
- }
427
- return receiver;
428
- }
429
- }
430
- const isString = (val) => typeof val === 'string';
431
-
432
- function YUVToRGB(buffer, image, alpha = 255) {
433
- const { width, height, chromaWidth, chromaHeight, dataY, dataU, dataV, strideY, strideU, strideV, } = buffer;
434
- const output = image.data;
435
- const hdec = depower(width / chromaWidth) | 0;
436
- const vdec = depower(height / chromaHeight) | 0;
437
- const outStride = width << 2;
438
- let YPtr = 0;
439
- let Y0Ptr = 0;
440
- let Y1Ptr = 0;
441
- let CbPtr = 0;
442
- let CrPtr = 0;
443
- let outPtr = 0;
444
- let outPtr0 = 0;
445
- let outPtr1 = 0;
446
- let colorCb = 0;
447
- let colorCr = 0;
448
- let multY = 0;
449
- let multCrR = 0;
450
- let multCbCrG = 0;
451
- let multCbB = 0;
452
- let x = 0;
453
- let y = 0;
454
- let xdec = 0;
455
- let ydec = 0;
456
- // eslint-disable-next-line no-constant-condition
457
- if (hdec === 1 && vdec === 1) {
458
- // Optimize for 4:2:0, which is most common
459
- outPtr0 = 0;
460
- outPtr1 = outStride;
461
- ydec = 0;
462
- for (y = 0; y < height; y += 2) {
463
- Y0Ptr = (y * strideY) | 0;
464
- Y1Ptr = (Y0Ptr + strideY) | 0;
465
- CbPtr = (ydec * strideU) | 0;
466
- CrPtr = (ydec * strideV) | 0;
467
- for (x = 0; x < width; x += 2) {
468
- colorCb = dataU[CbPtr++] | 0;
469
- colorCr = dataV[CrPtr++] | 0;
470
- // Quickie YUV conversion
471
- // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion
472
- // multiplied by 256 for integer-friendliness
473
- multCrR = (((409 * colorCr) | 0) - 57088) | 0;
474
- multCbCrG = (((100 * colorCb) | 0) + ((208 * colorCr) | 0) - 34816) | 0;
475
- multCbB = (((516 * colorCb) | 0) - 70912) | 0;
476
- multY = (298 * dataY[Y0Ptr++]) | 0;
477
- output[outPtr0] = (multY + multCrR) >> 8;
478
- output[outPtr0 + 1] = (multY - multCbCrG) >> 8;
479
- output[outPtr0 + 2] = (multY + multCbB) >> 8;
480
- output[outPtr0 + 3] = alpha;
481
- outPtr0 += 4;
482
- multY = (298 * dataY[Y0Ptr++]) | 0;
483
- output[outPtr0] = (multY + multCrR) >> 8;
484
- output[outPtr0 + 1] = (multY - multCbCrG) >> 8;
485
- output[outPtr0 + 2] = (multY + multCbB) >> 8;
486
- output[outPtr0 + 3] = alpha;
487
- outPtr0 += 4;
488
- multY = (298 * dataY[Y1Ptr++]) | 0;
489
- output[outPtr1] = (multY + multCrR) >> 8;
490
- output[outPtr1 + 1] = (multY - multCbCrG) >> 8;
491
- output[outPtr1 + 2] = (multY + multCbB) >> 8;
492
- output[outPtr1 + 3] = alpha;
493
- outPtr1 += 4;
494
- multY = (298 * dataY[Y1Ptr++]) | 0;
495
- output[outPtr1] = (multY + multCrR) >> 8;
496
- output[outPtr1 + 1] = (multY - multCbCrG) >> 8;
497
- output[outPtr1 + 2] = (multY + multCbB) >> 8;
498
- output[outPtr1 + 3] = alpha;
499
- outPtr1 += 4;
500
- }
501
- outPtr0 += outStride;
502
- outPtr1 += outStride;
503
- ydec++;
504
- }
505
- }
506
- else {
507
- outPtr = 0;
508
- for (y = 0; y < height; y++) {
509
- xdec = 0;
510
- ydec = y >> vdec;
511
- YPtr = (y * strideY) | 0;
512
- CbPtr = (ydec * strideU) | 0;
513
- CrPtr = (ydec * strideV) | 0;
514
- for (x = 0; x < width; x++) {
515
- xdec = x >> hdec;
516
- colorCb = dataU[CbPtr + xdec] | 0;
517
- colorCr = dataV[CrPtr + xdec] | 0;
518
- // Quickie YUV conversion
519
- // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion
520
- // multiplied by 256 for integer-friendliness
521
- multCrR = (((409 * colorCr) | 0) - 57088) | 0;
522
- multCbCrG = (((100 * colorCb) | 0) + ((208 * colorCr) | 0) - 34816) | 0;
523
- multCbB = (((516 * colorCb) | 0) - 70912) | 0;
524
- multY = (298 * dataY[YPtr++]) | 0;
525
- output[outPtr] = (multY + multCrR) >> 8;
526
- output[outPtr + 1] = (multY - multCbCrG) >> 8;
527
- output[outPtr + 2] = (multY + multCbB) >> 8;
528
- // const Y = dataY[YPtr++];
529
- // const U = dataU[CbPtr + xdec];
530
- // const V = dataV[CrPtr + xdec];
531
- // const [R, G, B] = YUV2RGB([Y, U, V]);
532
- // const R = YUVToR(Y, U, V);
533
- // const G = YUVToG(Y, U, V);
534
- // const B = YUVToB(Y, U, V);
535
- // output[outPtr] = R;
536
- // output[outPtr + 1] = G;
537
- // output[outPtr + 2] = B;
538
- output[outPtr + 3] = alpha;
539
- outPtr += 4;
540
- }
541
- }
542
- }
543
- }
544
- function depower(ratio) {
545
- let shiftCount = 0;
546
- let n = ratio >> 1;
547
- while (n !== 0) {
548
- n >>= 1;
549
- shiftCount++;
550
- }
551
- if (ratio !== 1 << shiftCount) {
552
- throw Error(`chroma plane dimensions must be power of 2 ratio to luma plane dimensions; got ${ratio}`);
553
- }
554
- return shiftCount;
555
- }
556
-
557
- // export const enum VideoFrameBufferType {
558
- var VideoFrameBufferType;
559
- (function (VideoFrameBufferType) {
560
- VideoFrameBufferType[VideoFrameBufferType["kNative"] = 0] = "kNative";
561
- VideoFrameBufferType[VideoFrameBufferType["kRGBA"] = 1] = "kRGBA";
562
- VideoFrameBufferType[VideoFrameBufferType["kABGR"] = 2] = "kABGR";
563
- VideoFrameBufferType[VideoFrameBufferType["kI420"] = 3] = "kI420";
564
- VideoFrameBufferType[VideoFrameBufferType["kI420A"] = 4] = "kI420A";
565
- VideoFrameBufferType[VideoFrameBufferType["kI444"] = 5] = "kI444";
566
- })(VideoFrameBufferType || (VideoFrameBufferType = {}));
567
- function I420DataSize(height, strideY, strideU, strideV) {
568
- return strideY * height + (strideU + strideV) * ((height + 1) / 2);
569
- }
570
- class I420Buffer {
571
- constructor(builder) {
572
- this.type = VideoFrameBufferType.kI420;
573
- this.width = builder.width;
574
- this.height = builder.height;
575
- this.strideY = builder.strideY || this.width;
576
- this.strideU = builder.strideU || this.chromaWidth;
577
- this.strideV = builder.strideV || this.chromaWidth;
578
- const hasdata = builder.dataY && builder.dataU && builder.dataV;
579
- // @ts-ignore
580
- this.data =
581
- !hasdata &&
582
- AlignedMalloc(I420DataSize(this.height, this.strideY, this.strideU, this.strideV));
583
- this.dataY = builder.dataY || new Uint8ClampedArray(this.data, 0, this.strideY * this.height);
584
- this.dataU =
585
- builder.dataU ||
586
- new Uint8ClampedArray(this.data, this.strideY * this.height, this.strideU * this.chromaHeight);
587
- this.dataV =
588
- builder.dataV ||
589
- new Uint8ClampedArray(this.data, this.strideY * this.height + this.strideU * this.chromaHeight, this.strideV * this.chromaHeight);
590
- // this.dataY = builder.dataY || AlignedMalloc(this.strideY * this.height);
591
- // this.dataU =
592
- // builder.dataU ||
593
- // AlignedMalloc(this.strideU * this.chromaHeight);
594
- // this.dataV =
595
- // builder.dataV ||
596
- // AlignedMalloc(this.strideV * this.chromaHeight);
597
- }
598
- get chromaWidth() {
599
- return Math.floor((this.width + 1) / 2);
600
- }
601
- get chromaHeight() {
602
- return Math.floor((this.height + 1) / 2);
603
- }
604
- toI420() {
605
- return this;
606
- }
607
- getI420() {
608
- return this;
609
- }
610
- getI420A() {
611
- return undefined;
612
- }
613
- getI444() {
614
- return undefined;
615
- }
616
- }
617
- // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
618
- const kBufferAlignment = 64;
619
- function AlignedSize(size, alignment = kBufferAlignment) {
620
- const remainder = size % alignment;
621
- const aligned = remainder === 0 ? size : size + alignment - remainder;
622
- return aligned;
623
- }
624
- function AlignedMalloc(size, alignment = kBufferAlignment) {
625
- return new ArrayBuffer(AlignedSize(size, alignment));
626
- }
627
-
628
- class VideoFrame {
629
- constructor(builder) {
630
- this.buffer = builder.buffer;
631
- }
632
- get width() {
633
- return this.buffer.width;
634
- }
635
- get height() {
636
- return this.buffer.height;
637
- }
638
- }
639
-
640
- let suspended = false;
641
- if (typeof document !== 'undefined' && typeof __INVISIBLE_SUSPEND__ !== 'undefined') {
642
- document.addEventListener('visibilitychange', () => {
643
- suspended = document.visibilityState === 'hidden';
644
- });
645
- }
646
- class VideoRenderer {
647
- constructor() {
648
- this.frameCounts = 0;
649
- this.droppedFrameCounts = 0;
650
- this.pending = false;
651
- }
652
- clear() {
653
- console.log('abstract clear()');
654
- }
655
- render(frame) {
656
- console.log('abstract render()', frame);
657
- }
658
- onFrame(frame, immediate = false) {
659
- // fps reduction
660
- if (!this.pending && !suspended) {
661
- if (immediate) {
662
- this.render(frame);
663
- }
664
- else {
665
- requestAnimationFrame(() => this.render(frame));
666
- }
667
- requestAnimationFrame(() => (this.pending = false));
668
- this.pending = true;
669
- }
670
- else {
671
- this.droppedFrameCounts++;
672
-
673
- !(this.droppedFrameCounts % 600) &&
674
- console.log(`renderer drop frame due to fps reduction: ${this.droppedFrameCounts}`);
675
- }
676
- this.frameCounts++;
677
- }
678
- }
679
-
680
- class CanvasVideoRenderer extends VideoRenderer {
681
- constructor(canvas) {
682
- super();
683
- this.canvas = canvas;
684
- this.width = canvas.width;
685
- this.height = canvas.height;
686
- // this.canvas.style.display = 'block';
687
- this.context = this.canvas.getContext('2d');
688
- // this.context.setTransform(1, 0, 0, 1, 0, 0);
689
- }
690
- setSize(width, height) {
691
- this.canvas.width = width;
692
- this.canvas.height = height;
693
- this.width = width;
694
- this.height = height;
695
- }
696
- clear() {
697
- this.context.clearRect(0, 0, this.width, this.height);
698
- }
699
- render(frame) {
700
- const { width, height, buffer } = frame;
701
- if (width !== this.width || height !== this.height) {
702
- this.setSize(width, height);
703
- }
704
- this.clear();
705
- let image;
706
- switch (buffer.type) {
707
- case VideoFrameBufferType.kI420:
708
- image = this.context.createImageData(width, height);
709
- YUVToRGB(buffer, image);
710
- break;
711
- case VideoFrameBufferType.kABGR:
712
- image = buffer.toImage(this.context);
713
- break;
714
- case VideoFrameBufferType.kNative:
715
- image = buffer.image;
716
- break;
717
- default:
718
- console.warn(`Frame type: ${buffer.type} is not supported.`);
719
- return;
720
- }
721
- this.context.putImageData(image, 0, 0, 0, 0, width, height);
722
- }
723
- }
724
-
725
- const VS = `
726
- precision mediump float;
727
-
728
- attribute vec2 aVertexPosition;
729
- attribute vec2 aTextureCoord;
730
-
731
- uniform vec2 uResolution;
732
-
733
- varying vec2 vTextureCoord;
734
-
735
- void main(void) {
736
- // convert the rectangle from pixels to 0.0 to 1.0
737
- vec2 zeroToOne = aVertexPosition / uResolution;
738
-
739
- // convert from 0 -> 1 to 0 -> 2
740
- vec2 zeroToTwo = zeroToOne * 2.0;
741
-
742
- // convert from 0 -> 2 to -1 -> +1 (clipspace)
743
- vec2 clipSpace = zeroToTwo - 1.0;
744
-
745
- gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
746
-
747
- vTextureCoord = aTextureCoord;
748
- }
749
- `;
750
- const FS = `
751
- precision mediump float;
752
-
753
- uniform sampler2D uTextureY;
754
- uniform sampler2D uTextureU;
755
- uniform sampler2D uTextureV;
756
-
757
- varying vec2 vTextureCoord;
758
-
759
- const mat4 YUV2RGB = mat4(
760
- 1.1643828125, 0, 1.59602734375, -.87078515625,
761
- 1.1643828125, -.39176171875, -.81296875, .52959375,
762
- 1.1643828125, 2.017234375, 0, -1.081390625,
763
- 0, 0, 0, 1
764
- );
765
-
766
- void main(void) {
767
- gl_FragColor = vec4(
768
- texture2D(uTextureY, vTextureCoord).x,
769
- texture2D(uTextureU, vTextureCoord).x,
770
- texture2D(uTextureV, vTextureCoord).x,
771
- 1
772
- ) * YUV2RGB;
773
- }
774
- `;
775
- function buildProgram(gl) {
776
- // Create the program and shaders
777
- const program = gl.createProgram();
778
- const vertexShader = buildShader(gl, gl.VERTEX_SHADER, VS);
779
- const fragmentShader = buildShader(gl, gl.FRAGMENT_SHADER, FS);
780
- if (!program || !vertexShader || !fragmentShader) {
781
- return null;
782
- }
783
- // Attach an link the shader
784
- gl.attachShader(program, vertexShader);
785
- gl.attachShader(program, fragmentShader);
786
- gl.linkProgram(program);
787
- // Add error handling
788
- if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
789
- const error = gl.getError();
790
- const status = gl.getProgramParameter(program, gl.VALIDATE_STATUS);
791
-
792
- console.error(`Could not initialise shader.\n` + `VALIDATE_STATUS: ${status}\n` + `ERROR: ${error}`);
793
- return null;
794
- }
795
- // Delete the shader
796
- gl.deleteShader(fragmentShader);
797
- gl.deleteShader(vertexShader);
798
- // Enable program
799
- gl.useProgram(program);
800
- return program;
801
- }
802
- function buildShader(gl, type, source) {
803
- const shader = gl.createShader(type);
804
- if (!shader) {
805
- console.error(`WebGL createShader(type: ${type}) failed.`);
806
- return null;
807
- }
808
- // Add shader source
809
- gl.shaderSource(shader, source);
810
- // Compile shader
811
- gl.compileShader(shader);
812
- // Add error handling
813
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
814
- console.error(`WebGL compileShader() failed.\n` + `${gl.getShaderInfoLog(shader)}`);
815
- return null;
816
- }
817
- return shader;
818
- }
819
- function buildBuffer(gl, program, type, identifier, size, structure, count) {
820
- const buffer = {
821
- buffer: gl.createBuffer(),
822
- location: -1,
823
- identifier,
824
- size,
825
- structure,
826
- count,
827
- };
828
- // Set the location
829
- switch (type) {
830
- case 'attribute':
831
- buffer.location = gl.getAttribLocation(program, identifier);
832
- break;
833
- case 'uniform':
834
- buffer.location = gl.getUniformLocation(program, identifier);
835
- break;
836
- }
837
- // Create the buffer if count is provided
838
- if (count) {
839
- buffer.data = new Float32Array(count * size);
840
- }
841
- // Return the buffer
842
- return buffer;
843
- }
844
- function buildTexture(gl, program, type, identifier, textureId, unit) {
845
- const texture = {
846
- texture: gl.createTexture(),
847
- textureId,
848
- location: gl.getUniformLocation(program, identifier),
849
- identifier,
850
- unit,
851
- };
852
- // Bind texture
853
- gl.activeTexture(textureId);
854
- gl.bindTexture(gl.TEXTURE_2D, texture.texture);
855
- // Set the parameters.
856
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
857
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
858
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
859
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
860
- gl.uniform1i(texture.location, unit);
861
- return texture;
862
- }
863
- function setBufferData(index, buffer, value) {
864
- if (isNumber(value)) {
865
- buffer.data[index * buffer.size] = value;
866
- }
867
- else {
868
- for (let i = value.length - 1; i >= 0; i--) {
869
- buffer.data[index * buffer.size + i] = value[i];
870
- }
871
- }
872
- }
873
- function setTextureData(gl, texture, data, width, height) {
874
- gl.activeTexture(texture.textureId);
875
- gl.bindTexture(gl.TEXTURE_2D, texture.texture);
876
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
877
- const error = gl.getError();
878
- if (error !== gl.NO_ERROR) {
879
- console.log('WebGL texImage2D() failed.', error);
880
- }
881
- }
882
- function setAttribBuffer(gl, buffer) {
883
- gl.enableVertexAttribArray(buffer.location);
884
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buffer);
885
- gl.bufferData(gl.ARRAY_BUFFER, buffer.data, gl.STATIC_DRAW);
886
- gl.vertexAttribPointer(buffer.location, buffer.size, gl.FLOAT, false, 0, 0);
887
- }
888
- function setUniformBuffer(gl, buffer) {
889
- const location = buffer.location;
890
- const data = buffer.data;
891
- switch (buffer.structure) {
892
- case '2f':
893
- gl.uniform2f(location, data[0], data[1]);
894
- break;
895
- case '2fv':
896
- gl.uniform2fv(location, data);
897
- break;
898
- case '3f':
899
- gl.uniform3f(location, data[0], data[1], data[2]);
900
- break;
901
- case '3fv':
902
- gl.uniform3fv(location, data);
903
- break;
904
- case '4f':
905
- gl.uniform4f(location, data[0], data[1], data[2], data[3]);
906
- break;
907
- case '4fv':
908
- gl.uniform4fv(location, data);
909
- break;
910
- }
911
- }
912
- function isNumber(value) {
913
- return !Number.isNaN(parseFloat(value)) && Number.isFinite(value);
914
- }
915
-
916
- class WebGLVideoRenderer extends VideoRenderer {
917
- constructor(canvas) {
918
- super();
919
- this.attributes = null;
920
- this.uniforms = null;
921
- this.textures = null;
922
- this.parameters = {
923
- alpha: true,
924
- antialias: true,
925
- depth: true,
926
- desynchronized: true,
927
- // Don't try to use software GL rendering!
928
- failIfMajorPerformanceCaveat: true,
929
- // Don't trigger discrete GPU in multi-GPU systems
930
- powerPreference: 'low-power',
931
- premultipliedAlpha: true,
932
- // In case we need to capture the resulting output.
933
- preserveDrawingBuffer: false,
934
- stencil: true,
935
- };
936
- // canvas.style.display = 'block';
937
- this.canvas = canvas;
938
- this.width = canvas.width;
939
- this.height = canvas.height;
940
- this.gl = this.canvas.getContext('webgl');
941
- // this.context.setTransform(1, 0, 0, 1, 0, 0);
942
- this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
943
- this.gl.enable(this.gl.DEPTH_TEST);
944
- this.gl.depthFunc(this.gl.LEQUAL);
945
- }
946
- setSize(width, height) {
947
- this.canvas.width = width;
948
- this.canvas.height = height;
949
- this.width = width;
950
- this.height = height;
951
- this.gl.viewport(0, 0, width, height);
952
- }
953
- clear() {
954
- this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
955
- }
956
- grab() {
957
- if (isOffscreenCanvas(this.canvas)) {
958
- return this.canvas.transferToImageBitmap();
959
- }
960
- }
961
- dispose() {
962
- // eslint-disable-next-line camelcase
963
- let context;
964
- if ((context = this.gl.getExtension('WEBGL_lose_context'))) {
965
- context.loseContext();
966
- }
967
- }
968
- render(frame) {
969
- const { width, height,
970
- // chromaWidth,
971
- chromaHeight, dataY, dataU, dataV, strideY, strideU, strideV, } = frame.buffer;
972
- if (this.gl.isContextLost()) {
973
- this.gl = this.canvas.getContext('webgl');
974
- }
975
- if (width !== this.width || height !== this.height) {
976
- this.setSize(width, height);
977
- }
978
- this.clear();
979
- if (!this.program) {
980
- this.program = buildProgram(this.gl);
981
- // Add the program attributes
982
- this.attributes = {
983
- position: buildBuffer(this.gl, this.program, 'attribute', 'aVertexPosition', 2, 'v2'),
984
- texcoord: buildBuffer(this.gl, this.program, 'attribute', 'aTextureCoord', 2, 'v2'),
985
- };
986
- // Add the program uniforms
987
- this.uniforms = {
988
- resolution: buildBuffer(this.gl, this.program, 'uniform', 'uResolution', 2, '2f', 1),
989
- };
990
- // Add the program texture
991
- this.textures = {
992
- y: buildTexture(this.gl, this.program, 'uniform', 'uTextureY', this.gl.TEXTURE0, 0),
993
- u: buildTexture(this.gl, this.program, 'uniform', 'uTextureU', this.gl.TEXTURE1, 1),
994
- v: buildTexture(this.gl, this.program, 'uniform', 'uTextureV', this.gl.TEXTURE2, 2),
995
- };
996
- }
997
- let buffer;
998
- let texture;
999
- const cropLeft = 0;
1000
- const cropTop = 0;
1001
- const cropWidth = width;
1002
- const cropHeight = height;
1003
- const textureX0 = cropLeft;
1004
- const textureX1 = cropLeft + cropWidth;
1005
- const textureY0 = cropTop + cropHeight;
1006
- const textureY1 = cropTop;
1007
- // 4 vertex, 1(x0,y0), 2(x1,y0), 3(x1,y1), 4(x0,y1)
1008
- // 0: 1,2,4/4,2,3
1009
- // 90: 2,3,1/1,3,4
1010
- // 180: 3,4,2/2,4,1
1011
- // 270: 4,1,3/3,1,2
1012
- // top-left (0, 0)
1013
- // top-right (1, 0)
1014
- // bottom-right (1, 1)
1015
- // bottom-left (0, 1)
1016
- const position = new Float32Array([
1017
- textureX0,
1018
- textureY0,
1019
- textureX1,
1020
- textureY0,
1021
- textureX0,
1022
- textureY1,
1023
- textureX0,
1024
- textureY1,
1025
- textureX1,
1026
- textureY0,
1027
- textureX1,
1028
- textureY1,
1029
- ]);
1030
- // top-left (0, 1)
1031
- // top-right (1, 1)
1032
- // bottom-right (1, 0)
1033
- // bottom-left (0, 0)
1034
- const textureX = width / strideY;
1035
- const texcoord = new Float32Array([0, 1, textureX, 1, 0, 0, 0, 0, textureX, 1, textureX, 0]);
1036
- // Build attribute buffers
1037
- const attributes = Object.keys(this.attributes);
1038
- attributes.forEach((attribute) => {
1039
- buffer = this.attributes[attribute];
1040
- // Update attribute buffer data
1041
- switch (attribute) {
1042
- case 'position':
1043
- buffer.data = new Float32Array(position.length);
1044
- setBufferData(0, buffer, position);
1045
- break;
1046
- case 'texcoord':
1047
- buffer.data = new Float32Array(texcoord.length);
1048
- setBufferData(0, buffer, texcoord);
1049
- break;
1050
- default:
1051
- return;
1052
- }
1053
- setAttribBuffer(this.gl, buffer);
1054
- });
1055
- // Build uniform buffers
1056
- setBufferData(0, this.uniforms.resolution, [width, height]);
1057
- // Update uniforms
1058
- const uniforms = Object.keys(this.uniforms);
1059
- uniforms.forEach((uniform) => {
1060
- buffer = this.uniforms[uniform];
1061
- // Update uniform buffer data
1062
- setUniformBuffer(this.gl, buffer);
1063
- });
1064
- // Update textures
1065
- const textures = Object.keys(this.textures);
1066
- textures.forEach((name) => {
1067
- texture = this.textures[name];
1068
- switch (name) {
1069
- case 'y':
1070
- setTextureData(this.gl, texture, dataY, strideY, height);
1071
- break;
1072
- case 'u':
1073
- setTextureData(this.gl, texture, dataU, strideU, chromaHeight);
1074
- break;
1075
- case 'v':
1076
- setTextureData(this.gl, texture, dataV, strideV, chromaHeight);
1077
- break;
1078
- }
1079
- });
1080
- // Draw those lovely triangles
1081
- this.gl.drawArrays(this.gl.TRIANGLES, 0, position.length / 2); // in vec2
1082
- }
1083
- }
1084
- function isOffscreenCanvas(val) {
1085
- return typeof OffscreenCanvas !== 'undefined' && val instanceof OffscreenCanvas;
1086
- }
1087
-
1088
- /// <reference types="emscripten" />
1089
- const DEFAULT_HEAP_TYPE = 'HEAPU8';
1090
- function createMemoryAllocator(native, type) {
1091
- return (length) => {
1092
- const { BYTES_PER_ELEMENT } = native[type || DEFAULT_HEAP_TYPE];
1093
- const bytes = length * BYTES_PER_ELEMENT;
1094
- const pointer = native._malloc(bytes);
1095
- const tuple = () => [pointer, bytes];
1096
- // malloc() might cause wasm memory growth, which will detach 'heap' buffer
1097
- const view = (normalize = true) => {
1098
- const v = native[type || DEFAULT_HEAP_TYPE].subarray(pointer / BYTES_PER_ELEMENT, pointer + length);
1099
- if (normalize && typeof v.constructor !== 'undefined') {
1100
- return new v.constructor(v.buffer, v.byteOffset, length);
1101
- }
1102
- console.log('unnormalized array view has unexpected length');
1103
- return v;
1104
- };
1105
- const free = () => native._free(pointer);
1106
- return {
1107
- BYTES_PER_ELEMENT,
1108
- pointer,
1109
- length,
1110
- bytes,
1111
- tuple,
1112
- view,
1113
- free,
1114
- };
1115
- };
1116
- }
1117
- function createMemoryViewer(native, type) {
1118
- return (begin, length, normalize = true) => {
1119
- const heap = native[type || DEFAULT_HEAP_TYPE];
1120
- const { BYTES_PER_ELEMENT } = heap;
1121
- const view = heap.subarray(begin / BYTES_PER_ELEMENT, begin + length);
1122
- if (normalize && typeof view.constructor !== 'undefined') {
1123
- return new view.constructor(view.buffer, view.byteOffset, length);
1124
- }
1125
- console.log('unnormalized array view has unexpected length');
1126
- return view;
1127
- };
1128
- }
1129
-
1130
- function open(name, store) {
1131
- const request = indexedDB.open(name);
1132
- request.onupgradeneeded = () => request.result.createObjectStore(store);
1133
- const promise = make(request);
1134
- return (mode, callback) => promise.then((db) => callback(db.transaction(store, mode).objectStore(store)));
1135
- }
1136
- const LAZY_INSTANCE = (factory) => {
1137
- let instance;
1138
- return (...args) => {
1139
- if (!instance) {
1140
- instance = factory();
1141
- }
1142
- return instance(...args);
1143
- };
1144
- };
1145
- const LAZY_GLOBAL_STORE = LAZY_INSTANCE(() => open('LINE-UI', 'key-value'));
1146
- function get(key, store = LAZY_GLOBAL_STORE) {
1147
- return store('readonly', (store) => make(store.get(key)));
1148
- }
1149
- function clear(store = LAZY_GLOBAL_STORE) {
1150
- return store('readwrite', (store) => {
1151
- store.clear();
1152
- return make(store.transaction);
1153
- });
1154
- }
1155
- function make(request) {
1156
- return new Promise((resolve, reject) => {
1157
- // @ts-ignore - file size hacks
1158
- request.oncomplete = request.onsuccess = () => resolve(request.result);
1159
- // @ts-ignore - file size hacks
1160
- request.onabort = request.onerror = () => reject(request.error);
1161
- });
1162
- }
1163
-
1164
- /// <reference types="emscripten" />
1165
- var SFUTransportType;
1166
- (function (SFUTransportType) {
1167
- SFUTransportType[SFUTransportType["kAudio"] = 1] = "kAudio";
1168
- SFUTransportType[SFUTransportType["kVideo"] = 2] = "kVideo";
1169
- SFUTransportType[SFUTransportType["kData"] = 3] = "kData";
1170
- SFUTransportType[SFUTransportType["kAnnotation"] = 4] = "kAnnotation";
1171
- SFUTransportType[SFUTransportType["kMessage"] = 5] = "kMessage";
1172
- })(SFUTransportType || (SFUTransportType = {}));
1173
- var SFUTransportOrient;
1174
- (function (SFUTransportOrient) {
1175
- SFUTransportOrient[SFUTransportOrient["kSend"] = 1] = "kSend";
1176
- SFUTransportOrient[SFUTransportOrient["kRecv"] = 2] = "kRecv";
1177
- SFUTransportOrient[SFUTransportOrient["kBoth"] = 3] = "kBoth";
1178
- })(SFUTransportOrient || (SFUTransportOrient = {}));
1179
- var SFUUserRole;
1180
- (function (SFUUserRole) {
1181
- SFUUserRole[SFUUserRole["kInteractive"] = 1] = "kInteractive";
1182
- SFUUserRole[SFUUserRole["kBroadcast"] = 2] = "kBroadcast";
1183
- })(SFUUserRole || (SFUUserRole = {}));
1184
- var SFUReason;
1185
- (function (SFUReason) {
1186
- SFUReason[SFUReason["kOK"] = 0] = "kOK";
1187
- SFUReason[SFUReason["kError"] = 320200] = "kError";
1188
- SFUReason[SFUReason["kExisted"] = 320201] = "kExisted";
1189
- SFUReason[SFUReason["kNetworkError"] = 320202] = "kNetworkError";
1190
- SFUReason[SFUReason["kMCFailed"] = 320203] = "kMCFailed";
1191
- SFUReason[SFUReason["kMSSFailed"] = 320204] = "kMSSFailed";
1192
- SFUReason[SFUReason["kMSSLost"] = 320205] = "kMSSLost";
1193
- SFUReason[SFUReason["kAuthFailed"] = 320206] = "kAuthFailed";
1194
- SFUReason[SFUReason["kLoadFailed"] = 320207] = "kLoadFailed";
1195
- SFUReason[SFUReason["kNoImplemented"] = 320208] = "kNoImplemented";
1196
- })(SFUReason || (SFUReason = {}));
1197
- var SFUTransportStatus;
1198
- (function (SFUTransportStatus) {
1199
- SFUTransportStatus[SFUTransportStatus["kReconnecting"] = 320100] = "kReconnecting";
1200
- SFUTransportStatus[SFUTransportStatus["kReconnectOK"] = 320101] = "kReconnectOK";
1201
- SFUTransportStatus[SFUTransportStatus["kReconnectNG"] = 320102] = "kReconnectNG";
1202
- })(SFUTransportStatus || (SFUTransportStatus = {}));
1203
- var SFUEndpointStatus;
1204
- (function (SFUEndpointStatus) {
1205
- SFUEndpointStatus[SFUEndpointStatus["kHandshakeOK"] = 100] = "kHandshakeOK";
1206
- SFUEndpointStatus[SFUEndpointStatus["kHandshakeNG"] = 101] = "kHandshakeNG";
1207
- SFUEndpointStatus[SFUEndpointStatus["kConnectOK"] = 102] = "kConnectOK";
1208
- SFUEndpointStatus[SFUEndpointStatus["kConnectNG"] = 103] = "kConnectNG";
1209
- })(SFUEndpointStatus || (SFUEndpointStatus = {}));
1210
- var TransportType;
1211
- (function (TransportType) {
1212
- TransportType[TransportType["kSignal"] = 0] = "kSignal";
1213
- TransportType[TransportType["kData"] = 1] = "kData";
1214
- })(TransportType || (TransportType = {}));
1215
- var VideoEncodeMode;
1216
- (function (VideoEncodeMode) {
1217
- VideoEncodeMode[VideoEncodeMode["kVeryfast"] = 0] = "kVeryfast";
1218
- VideoEncodeMode[VideoEncodeMode["kUltrafast"] = 1] = "kUltrafast";
1219
- VideoEncodeMode[VideoEncodeMode["kUltrafastPlus"] = 2] = "kUltrafastPlus";
1220
- })(VideoEncodeMode || (VideoEncodeMode = {}));
1221
- // SFUTransportType
1222
- // type VideoChannelType = SFUTransportType;
1223
- var VideoChannelType;
1224
- (function (VideoChannelType) {
1225
- // kAudio = 1,
1226
- VideoChannelType[VideoChannelType["kVideo"] = 2] = "kVideo";
1227
- VideoChannelType[VideoChannelType["kData"] = 3] = "kData";
1228
- VideoChannelType[VideoChannelType["kAnnotation"] = 4] = "kAnnotation";
1229
- VideoChannelType[VideoChannelType["kMessage"] = 5] = "kMessage";
1230
- })(VideoChannelType || (VideoChannelType = {}));
1231
- // SFUTransportOrient
1232
- // type VideoChannelOrient = SFUTransportOrient;
1233
- var VideoChannelOrient;
1234
- (function (VideoChannelOrient) {
1235
- VideoChannelOrient[VideoChannelOrient["kInactive"] = 0] = "kInactive";
1236
- VideoChannelOrient[VideoChannelOrient["kSend"] = 1] = "kSend";
1237
- VideoChannelOrient[VideoChannelOrient["kRecv"] = 2] = "kRecv";
1238
- VideoChannelOrient[VideoChannelOrient["kBoth"] = 3] = "kBoth";
1239
- })(VideoChannelOrient || (VideoChannelOrient = {}));
1240
- var VideoChannelMode;
1241
- (function (VideoChannelMode) {
1242
- VideoChannelMode[VideoChannelMode["kNormal"] = 0] = "kNormal";
1243
- VideoChannelMode[VideoChannelMode["kSmooth"] = 1] = "kSmooth";
1244
- })(VideoChannelMode || (VideoChannelMode = {}));
1245
- var VideoRotation;
1246
- (function (VideoRotation) {
1247
- VideoRotation[VideoRotation["kRotation_0"] = 0] = "kRotation_0";
1248
- VideoRotation[VideoRotation["kRotation_90"] = 90] = "kRotation_90";
1249
- VideoRotation[VideoRotation["kRotation_180"] = 180] = "kRotation_180";
1250
- VideoRotation[VideoRotation["kRotation_270"] = 270] = "kRotation_270";
1251
- })(VideoRotation || (VideoRotation = {}));
1252
- var DataType;
1253
- (function (DataType) {
1254
- DataType[DataType["kCoopration"] = 1] = "kCoopration";
1255
- DataType[DataType["kRemoteControl"] = 2] = "kRemoteControl";
1256
- DataType[DataType["kSubtitleRealtime"] = 3] = "kSubtitleRealtime";
1257
- DataType[DataType["kSubtitleRecord"] = 4] = "kSubtitleRecord";
1258
- })(DataType || (DataType = {}));
1259
- var SubtitleSentenceAction;
1260
- (function (SubtitleSentenceAction) {
1261
- SubtitleSentenceAction[SubtitleSentenceAction["kCommon"] = 0] = "kCommon";
1262
- SubtitleSentenceAction[SubtitleSentenceAction["kShareStart"] = 1] = "kShareStart";
1263
- SubtitleSentenceAction[SubtitleSentenceAction["kShareEnd"] = 2] = "kShareEnd";
1264
- SubtitleSentenceAction[SubtitleSentenceAction["kCoopStart"] = 3] = "kCoopStart";
1265
- SubtitleSentenceAction[SubtitleSentenceAction["kCoopEnd"] = 4] = "kCoopEnd";
1266
- SubtitleSentenceAction[SubtitleSentenceAction["kServiceOver"] = 5] = "kServiceOver";
1267
- })(SubtitleSentenceAction || (SubtitleSentenceAction = {}));
1268
- var SubtitleSentenceStatus;
1269
- (function (SubtitleSentenceStatus) {
1270
- SubtitleSentenceStatus[SubtitleSentenceStatus["kStart"] = 0] = "kStart";
1271
- SubtitleSentenceStatus[SubtitleSentenceStatus["kChanging"] = 1] = "kChanging";
1272
- SubtitleSentenceStatus[SubtitleSentenceStatus["kEnd"] = 2] = "kEnd";
1273
- })(SubtitleSentenceStatus || (SubtitleSentenceStatus = {}));
1274
-
1275
- let native;
1276
- let alloc;
1277
- let view;
1278
- // visibilityState === 'hidden'
1279
- let suspended$1 = false;
1280
- let loglevel = 2;
1281
- let timer_factory;
1282
- const DEFAULT_FRAME_RATE = 33;
1283
- // const supportOffscreen = typeof OffscreenCanvas !== 'undefined';
1284
- const encode_coef = 0.3;
1285
- let encode_avg = 0;
1286
- let encode_busy = false;
1287
- const isWechatWorker = typeof worker !== 'undefined';
1288
- if (isWechatWorker) {
1289
- worker.onMessage((data) => {
1290
- worker.onmessage && worker.onmessage({ data });
1291
- });
1292
- }
1293
- // eslint-disable-next-line no-restricted-globals
1294
- const channel = new MojoChannel(isWechatWorker ? worker : self);
1295
- const engine = channel.receiver('video-engine-host');
1296
- engine.implement('init', (reply, [url, verbose = false]) => __awaiter(void 0, void 0, void 0, function* () {
1297
- let factory;
1298
- let wasmUrl;
1299
- if (isWechatWorker) {
1300
- const trailingSlash = (v) => (!v || v.endsWith('/') ? v : `${v}/`);
1301
- const [scriptUrl, wasmDir = ''] = url.split('?');
1302
- const scriptName = scriptUrl.substring(scriptUrl.lastIndexOf('/') + 1);
1303
- factory = require(scriptUrl);
1304
- wasmUrl = trailingSlash(wasmDir) + scriptName.replace(/\.js$/, '.wasm');
1305
- }
1306
- else {
1307
- importScripts(url);
1308
- factory = LIBSVC;
1309
- wasmUrl = url.replace(/\.js$/, '.wasm');
1310
- }
1311
- const wasmBinary = isWechatWorker
1312
- ? wasmUrl
1313
- : yield get(wasmUrl).catch(() => null);
1314
- // should clear cache if init failed
1315
- native = yield factory({ wasmBinary }).catch((error) => {
1316
- clear();
1317
- throw error;
1318
- });
1319
- alloc = createMemoryAllocator(native);
1320
- view = createMemoryViewer(native);
1321
- console.log(`LIBSVC: ${native.VideoChannel.Version()}`);
1322
- timer_factory = new native.TimerFactory({
1323
- start: (callback, delay) => setInterval(() => native.TimerFactory.Run(callback), delay),
1324
- stop: (id) => {
1325
- clearInterval(id);
1326
- },
1327
- });
1328
- native.VideoChannel.Init(timer_factory, (level, msg) => {
1329
- if (verbose || (level >= loglevel && true)) {
1330
- console.log(msg);
1331
- }
1332
- });
1333
- reply.resolve();
1334
- }));
1335
- engine.implement('exit', (reply) => {
1336
- native.VideoChannel.Exit();
1337
- timer_factory.delete();
1338
- reply.resolve();
1339
- });
1340
- engine.implement('debug', (reply, [level]) => {
1341
- loglevel = level;
1342
- reply.resolve();
1343
- });
1344
- engine.implement('suspend', (reply) => {
1345
- suspended$1 = true;
1346
- reply.resolve();
1347
- });
1348
- engine.implement('resume', (reply) => {
1349
- suspended$1 = false;
1350
- reply.resolve();
1351
- });
1352
- engine.implement('setup', (reply, [transportPR, type = VideoChannelType.kVideo]) => {
1353
- const cleanup = [];
1354
- const transport_host = channel.remote(transportPR);
1355
- const video_channel_host = channel.receiver();
1356
- cleanup.unshift(() => transport_host.break());
1357
- // setup transport proxy
1358
- const sfu_transport_proxy = new native.SFUTransportProxy({
1359
- Connect: (config) => {
1360
- const [pointer, length] = config.desc;
1361
- const desc = view(pointer, length).slice();
1362
- transport_host
1363
- .make('connect')
1364
- .transfer(desc.buffer)
1365
- .post(Object.assign(Object.assign({}, config), { desc }));
1366
- },
1367
- // main thread will disconnect the real sfu transport
1368
- Disconnect: () => {
1369
- if (!video_channel_host.valid)
1370
- return;
1371
- transport_host.make('disconnect').post();
1372
- },
1373
- Subscribe: (request, remove) => {
1374
- if (!video_channel_host.valid)
1375
- return;
1376
- const memory = request
1377
- .map((v) => v.desc)
1378
- .map(([pointer, length]) => view(pointer, length).slice());
1379
- transport_host
1380
- .make('subscribe')
1381
- .transfer(...memory.map((v) => v.buffer))
1382
- .post(request.map((v, i) => (Object.assign(Object.assign({}, v), { desc: memory[i] }))), remove.map((v) => v.ccid));
1383
- },
1384
- SendData: (data, meta) => {
1385
- const memory = data.map(([pointer, length]) => view(pointer, length).slice());
1386
- transport_host
1387
- .make('senddata')
1388
- .transfer(...memory.map((v) => v.buffer))
1389
- .post(memory, meta);
1390
- },
1391
- SendSingal: (data, length, ccid) => {
1392
- const memory = view(data, length).slice();
1393
- transport_host.make('sendsignal').transfer(memory.buffer).post(memory, ccid);
1394
- },
1395
- });
1396
- // setup transport
1397
- const video_channel = new native.VideoChannel(type);
1398
- video_channel.SetTransport(sfu_transport_proxy);
1399
- // setup source
1400
- const source = new native.FrameSource();
1401
- video_channel.SetSource(source);
1402
- let encoding = false;
1403
- let fps = DEFAULT_FRAME_RATE;
1404
- const startFrameSource = () => {
1405
- const id = setInterval(() => {
1406
- if (!source_host || !source_host.valid)
1407
- return;
1408
- source_host
1409
- .make('capture')
1410
- .invoke()
1411
- .then((buffer) => buffer && encode(buffer));
1412
- }, 1000 / fps);
1413
- return () => clearInterval(id);
1414
- };
1415
- let stopFrameSource;
1416
- const onstop = () => {
1417
- stopFrameSource && stopFrameSource();
1418
- stopFrameSource = null;
1419
- };
1420
- const onstart = () => {
1421
- fps && (stopFrameSource = startFrameSource());
1422
- };
1423
- source.on('onstart', () => {
1424
- encoding = true;
1425
- onstop();
1426
- onstart();
1427
- source_host && source_host.make('onstart').post();
1428
- });
1429
- source.on('onstop', () => {
1430
- encoding = false;
1431
- onstop();
1432
- source_host && source_host.make('onstop').post();
1433
- });
1434
- // setup sink
1435
- const sink = new native.FrameSink();
1436
- video_channel.SetSink(sink);
1437
- const toBufferBuilder = (frame, copy = true) => {
1438
- const { width, height, strideY, strideU, strideV } = frame;
1439
- const { dataY, dataU, dataV } = frame;
1440
- const viewY = view(dataY, strideY * height);
1441
- const viewU = view(dataU, strideU * Math.floor((height + 1) / 2));
1442
- const viewV = view(dataV, strideV * Math.floor((height + 1) / 2));
1443
- const builder = {
1444
- width,
1445
- height,
1446
- strideY,
1447
- strideU,
1448
- strideV,
1449
- dataY: copy ? viewY.slice() : viewY,
1450
- dataU: copy ? viewU.slice() : viewU,
1451
- dataV: copy ? viewV.slice() : viewV,
1452
- };
1453
- return builder;
1454
- };
1455
- sink.on('onframe', (ccid, frame) => {
1456
- if (suspended$1)
1457
- return;
1458
- const sink = sink_proxies.get(ccid);
1459
- if (!sink)
1460
- return;
1461
- const { renderer, loadeddata } = sink;
1462
- if (!loadeddata) {
1463
- sink.host.make('onloadeddata').post();
1464
- sink.loadeddata = true;
1465
- }
1466
- if (frame.width !== sink.width || frame.height !== sink.height) {
1467
- sink.width = frame.width;
1468
- sink.height = frame.height;
1469
- sink.host.make('onframechanged').post(sink.width, sink.height);
1470
- }
1471
- if (renderer) {
1472
- // YUV format
1473
- const buffer = new I420Buffer(toBufferBuilder(frame, false));
1474
- // ABGR format
1475
- // const { width, height } = frame;
1476
- // const memory = alloc(width * height * 4);
1477
- // frame.ToABGR(memory.pointer);
1478
- // const data = view(memory.pointer, memory.bytes);
1479
- // const buffer = new RGBBuffer({ width, height, data });
1480
- // renderer.onFrame(new VideoFrame({ buffer }), true);
1481
- // memory.free();
1482
- renderer.onFrame(new VideoFrame({ buffer }), true);
1483
- return;
1484
- }
1485
- // YUV format
1486
- const builder = toBufferBuilder(frame);
1487
- sink.host
1488
- .make('onframe')
1489
- .transfer(builder.dataY.buffer, builder.dataU.buffer, builder.dataV.buffer)
1490
- .post(builder);
1491
- });
1492
- let source_host;
1493
- const sink_proxies = new Map();
1494
- // setup cleanup
1495
- cleanup.unshift(() => {
1496
- video_channel.Leave();
1497
- video_channel.delete();
1498
- sfu_transport_proxy.delete();
1499
- source.delete();
1500
- sink.delete();
1501
- source_host && source_host.break();
1502
- source_host = null;
1503
- sink_proxies.forEach((v) => v.host.break());
1504
- sink_proxies.clear();
1505
- });
1506
- // impl video channel host
1507
- let channel_config;
1508
- const pending_actions = [];
1509
- video_channel_host.implement('mode', (reply, [mode]) => {
1510
- native.VideoChannel.EncodeMode(mode);
1511
- reply.resolve();
1512
- });
1513
- video_channel_host.implement('open', (reply, [config]) => {
1514
- channel_config = config;
1515
- if (channel_config.orient !== VideoChannelOrient.kInactive) {
1516
- video_channel.Join(config);
1517
- }
1518
- reply.resolve();
1519
- });
1520
- video_channel_host.implement('subscribe', (reply, [request, remove]) => {
1521
- if (connecting || channel_config.orient === VideoChannelOrient.kInactive) {
1522
- pending_actions.push(() => video_channel.Subscribe(request, remove));
1523
- }
1524
- else {
1525
- video_channel.Subscribe(request, remove);
1526
- }
1527
- remove.forEach((ccid) => {
1528
- const sink = sink_proxies.get(ccid);
1529
- if (!sink)
1530
- return;
1531
- sink.renderer && sink.renderer.clear();
1532
- sink.host.break();
1533
- sink_proxies.delete(ccid);
1534
- });
1535
- reply.resolve();
1536
- });
1537
- video_channel_host.implement('sendstats', (reply) => {
1538
- reply.resolve(encoding ? video_channel.SendStats() : null);
1539
- });
1540
- video_channel_host.implement('recvstats', (reply, [ccid]) => {
1541
- reply.resolve(video_channel.RecvStats(ccid));
1542
- });
1543
- video_channel_host.implement('sendreport', (reply) => {
1544
- reply.resolve(encoding ? video_channel.SendReport() : null);
1545
- });
1546
- video_channel_host.implement('recvreport', (reply, [ccid]) => {
1547
- reply.resolve(video_channel.RecvReport(ccid));
1548
- });
1549
- const encode = (buffer) => {
1550
- const tick = Date.now();
1551
- const { width, height, data } = buffer;
1552
- const stride = width * 4;
1553
- const memory = alloc(stride * height);
1554
- // copy memory to wasm
1555
- memory.view().set(data);
1556
- // convert ABGR to I420 via libyuv
1557
- const frame = native.I420Buffer.FromABGR(width, height, memory.pointer, stride);
1558
- // release ABGR heap
1559
- memory.free();
1560
- // pass frame to source
1561
- source.OnFrame(frame);
1562
- // release frame
1563
- frame.delete();
1564
- const since = Date.now() - tick;
1565
- encode_avg = encode_coef * since + (1 - encode_coef) * encode_avg;
1566
- if (!encode_busy && encode_avg > 120) {
1567
- encode_busy = true;
1568
- source_host && source_host.make('onbusy').post(encode_busy);
1569
- }
1570
- if (encode_busy && encode_avg < 60) {
1571
- encode_busy = false;
1572
- source_host && source_host.make('onbusy').post(encode_busy);
1573
- }
1574
- };
1575
- // source & sink related
1576
- video_channel_host.implement('encode', (reply, [buffer]) => {
1577
- reply.resolve();
1578
- encode(buffer);
1579
- });
1580
- video_channel_host.implement('setsource', (reply, [sourcePR, frameRate]) => {
1581
- if (source_host) {
1582
- source_host.break();
1583
- source_host = null;
1584
- }
1585
- if (sourcePR) {
1586
- source_host = channel.remote(sourcePR);
1587
- }
1588
- onframerate(frameRate);
1589
- reply.resolve(encoding);
1590
- });
1591
- video_channel_host.implement('setsink', (reply, [ccid, sinkPR, id]) => {
1592
- reply.resolve();
1593
- let sink = sink_proxies.get(ccid);
1594
- if (sink) {
1595
- sink.host.break();
1596
- sink_proxies.delete(ccid);
1597
- }
1598
- if (!sinkPR)
1599
- return;
1600
- sink = { host: channel.remote(sinkPR) };
1601
- sink_proxies.set(ccid, sink);
1602
- if (!id)
1603
- return;
1604
- {
1605
- const duplicate = Array.from(sink_proxies.entries()).filter(([, value]) => value.renderer === renderers[id - 1]);
1606
- if (duplicate.length) {
1607
- console.warn(`renderer[${id}] is already binded to ${duplicate.map(([key]) => key)}`);
1608
- }
1609
- }
1610
- sink.renderer = renderers[id - 1];
1611
- });
1612
- const onframerate = (frameRate = DEFAULT_FRAME_RATE) => {
1613
- if (fps === frameRate)
1614
- return;
1615
- fps = frameRate;
1616
- if (!stopFrameSource)
1617
- return;
1618
- onstop();
1619
- onstart();
1620
- };
1621
- video_channel_host.implement('setframerate', (reply, [frameRate]) => {
1622
- console.log(`framerate: ${frameRate}`);
1623
- onframerate(frameRate);
1624
- reply.resolve();
1625
- });
1626
- video_channel_host.implement('setorient', (reply, [orient]) => {
1627
- reply.resolve();
1628
- console.log(`orient: ${orient}`);
1629
- // no change
1630
- if (channel_config.orient === orient)
1631
- return;
1632
- const inactive = channel_config.orient === VideoChannelOrient.kInactive;
1633
- channel_config.orient = orient;
1634
- if (orient === VideoChannelOrient.kInactive) {
1635
- video_channel.Leave();
1636
- }
1637
- else if (inactive) {
1638
- video_channel.Join(channel_config);
1639
- connecting = true;
1640
- }
1641
- else if (connecting) {
1642
- pending_actions.push(() => video_channel.SetOrient(orient));
1643
- }
1644
- else {
1645
- video_channel.SetOrient(orient);
1646
- }
1647
- });
1648
- cleanup.unshift(() => onstop());
1649
- const renderers = [];
1650
- video_channel_host.implement('load', (reply, [canvas, webgl = true]) => {
1651
- const renderer = webgl ? new WebGLVideoRenderer(canvas) : new CanvasVideoRenderer(canvas);
1652
- reply.resolve(renderers.push(renderer));
1653
- });
1654
- video_channel_host.implement('unload', (reply, [id]) => {
1655
- reply.resolve();
1656
- const renderer = renderers[--id];
1657
- if (!renderer)
1658
- return;
1659
- if (renderer.gl) {
1660
- renderer.dispose();
1661
- }
1662
- const sinks = [...sink_proxies.entries()].filter(([, v]) => v.renderer === renderer);
1663
- if (sinks) {
1664
-
1665
- console.warn(`remove video sink for [${sinks.map(([v]) => v)}] due to renderer[${id}] is unloaded`);
1666
- sinks.forEach(([v]) => sink_proxies.delete(v));
1667
- }
1668
- renderers[id] = null;
1669
- // shrink renderers
1670
- if (id === renderers.length - 1) {
1671
- while (id >= 0 && !renderers[id--]) {
1672
- renderers.pop();
1673
- }
1674
- }
1675
- });
1676
- // sfu transport related
1677
- let connecting = false;
1678
- video_channel_host.implement('onjoin', (reply, [reason, data]) => {
1679
- const memory = alloc(data.length);
1680
- memory.view().set(data);
1681
- sfu_transport_proxy.onjoin(reason, memory.pointer, memory.bytes);
1682
- memory.free();
1683
- pending_actions.forEach((v) => v());
1684
- pending_actions.length = 0;
1685
- connecting = false;
1686
- reply.resolve();
1687
- });
1688
- video_channel_host.implement('onleave', (reply, [reason]) => {
1689
- sfu_transport_proxy.onleave(reason);
1690
- reply.resolve();
1691
- });
1692
- video_channel_host.implement('onstatus', (reply, [status, reason]) => {
1693
- sfu_transport_proxy.onstatus(status, reason);
1694
- if (status === SFUTransportStatus.kReconnectOK) {
1695
- pending_actions.forEach((v) => v());
1696
- pending_actions.length = 0;
1697
- }
1698
- else if (status === SFUTransportStatus.kReconnectNG) {
1699
- video_channel.Leave();
1700
- video_channel.Join(channel_config);
1701
- }
1702
- reply.resolve();
1703
- });
1704
- video_channel_host.implement('onsubscribe', (reply, [ccid, reason, data]) => {
1705
- const memory = alloc(data.length);
1706
- memory.view().set(data);
1707
- sfu_transport_proxy.onsubscribe(ccid, reason, memory.pointer, memory.bytes);
1708
- memory.free();
1709
- reply.resolve();
1710
- });
1711
- video_channel_host.implement('onsubscribeupdated', (reply, [requests]) => {
1712
- sfu_transport_proxy.onsubscribeupdated(requests);
1713
- reply.resolve();
1714
- });
1715
- video_channel_host.implement('onbitrate', (reply, [info]) => {
1716
- sfu_transport_proxy.onbitrate(info);
1717
- reply.resolve();
1718
- });
1719
- video_channel_host.implement('onsendstats', (reply, [stats]) => {
1720
- sfu_transport_proxy.onsendstats(stats);
1721
- reply.resolve();
1722
- });
1723
- video_channel_host.implement('onrecvstats', (reply, [stats]) => {
1724
- sfu_transport_proxy.onrecvstats(stats);
1725
- reply.resolve();
1726
- });
1727
- video_channel_host.implement('onsendreport', (reply, [report]) => {
1728
- sfu_transport_proxy.onsendreport(report);
1729
- reply.resolve();
1730
- });
1731
- video_channel_host.implement('ontimestamps', (reply) => {
1732
- sfu_transport_proxy.ontimestamps();
1733
- reply.resolve();
1734
- });
1735
- video_channel_host.implement('onmediasync', (reply, [timestamps]) => {
1736
- sfu_transport_proxy.onmediasync(timestamps);
1737
- reply.resolve();
1738
- });
1739
- video_channel_host.implement('onsignal', (reply, [data]) => {
1740
- const memory = alloc(data.length);
1741
- memory.view().set(data);
1742
- sfu_transport_proxy.onsignal(memory.pointer, memory.bytes);
1743
- memory.free();
1744
- reply.resolve();
1745
- });
1746
- video_channel_host.implement('ondata', (reply, [data, ccid, time]) => {
1747
- const memory = alloc(data.length);
1748
- memory.view().set(data);
1749
- sfu_transport_proxy.ondata(memory.pointer, memory.bytes, ccid, time, -1);
1750
- memory.free();
1751
- reply.resolve();
1752
- });
1753
- // cleanup
1754
- video_channel_host.onbreak = () => {
1755
- cleanup.forEach((v) => v());
1756
- cleanup.length = 0;
1757
- };
1758
- reply.resolve(`${video_channel_host}`);
1759
- });
1760
- engine.implement('setup2', (reply, [transportPR, type = VideoChannelType.kMessage]) => {
1761
- const cleanup = [];
1762
- const transport_host = channel.remote(transportPR);
1763
- const data_channel_host = channel.receiver();
1764
- cleanup.unshift(() => transport_host.break());
1765
- // setup transport proxy
1766
- const sfu_transport_proxy = new native.SFUTransportProxy({
1767
- Connect: (config) => {
1768
- const [pointer, length] = config.desc;
1769
- const desc = view(pointer, length).slice();
1770
- transport_host
1771
- .make('connect')
1772
- .transfer(desc.buffer)
1773
- .post(Object.assign(Object.assign({}, config), { desc }));
1774
- },
1775
- // main thread will disconnect the real sfu transport
1776
- Disconnect: () => {
1777
- if (!data_channel_host.valid)
1778
- return;
1779
- transport_host.make('disconnect').post();
1780
- },
1781
- Subscribe: (request, remove) => {
1782
- if (!data_channel_host.valid)
1783
- return;
1784
- const memory = request
1785
- .map((v) => v.desc)
1786
- .map(([pointer, length]) => view(pointer, length).slice());
1787
- transport_host
1788
- .make('subscribe')
1789
- .transfer(...memory.map((v) => v.buffer))
1790
- .post(request.map((v, i) => (Object.assign(Object.assign({}, v), { desc: memory[i] }))), remove.map((v) => v.ccid));
1791
- },
1792
- SendData: (data, meta) => {
1793
- const memory = data.map(([pointer, length]) => view(pointer, length).slice());
1794
- transport_host
1795
- .make('senddata')
1796
- .transfer(...memory.map((v) => v.buffer))
1797
- .post(memory, meta);
1798
- },
1799
- SendSingal: (data, length, ccid) => {
1800
- const memory = view(data, length).slice();
1801
- transport_host.make('sendsignal').transfer(memory.buffer).post(memory, ccid);
1802
- },
1803
- });
1804
- // setup transport
1805
- const data_channel = new native.DataChannel(type);
1806
- data_channel.SetTransport(sfu_transport_proxy);
1807
- // sfu transport related
1808
- data_channel_host.implement('onjoin', (reply, [reason, data]) => {
1809
- const memory = alloc(data.length);
1810
- memory.view().set(data);
1811
- sfu_transport_proxy.onjoin(reason, memory.pointer, memory.bytes);
1812
- memory.free();
1813
- reply.resolve();
1814
- });
1815
- data_channel_host.implement('onleave', (reply, [reason]) => {
1816
- sfu_transport_proxy.onleave(reason);
1817
- reply.resolve();
1818
- });
1819
- data_channel_host.implement('onstatus', (reply, [status, reason]) => {
1820
- sfu_transport_proxy.onstatus(status, reason);
1821
- reply.resolve();
1822
- });
1823
- data_channel_host.implement('onsubscribe', (reply, [ccid, reason, data]) => {
1824
- const memory = alloc(data.length);
1825
- memory.view().set(data);
1826
- sfu_transport_proxy.onsubscribe(ccid, reason, memory.pointer, memory.bytes);
1827
- memory.free();
1828
- reply.resolve();
1829
- });
1830
- data_channel_host.implement('onsubscribeupdated', (reply, [requests]) => {
1831
- sfu_transport_proxy.onsubscribeupdated(requests);
1832
- reply.resolve();
1833
- });
1834
- data_channel_host.implement('onbitrate', (reply, [info]) => {
1835
- sfu_transport_proxy.onbitrate(info);
1836
- reply.resolve();
1837
- });
1838
- data_channel_host.implement('onsendstats', (reply, [stats]) => {
1839
- sfu_transport_proxy.onsendstats(stats);
1840
- reply.resolve();
1841
- });
1842
- data_channel_host.implement('onrecvstats', (reply, [stats]) => {
1843
- sfu_transport_proxy.onrecvstats(stats);
1844
- reply.resolve();
1845
- });
1846
- data_channel_host.implement('onsendreport', (reply, [report]) => {
1847
- sfu_transport_proxy.onsendreport(report);
1848
- reply.resolve();
1849
- });
1850
- data_channel_host.implement('ontimestamps', (reply) => {
1851
- sfu_transport_proxy.ontimestamps();
1852
- reply.resolve();
1853
- });
1854
- data_channel_host.implement('onmediasync', (reply, [timestamps]) => {
1855
- sfu_transport_proxy.onmediasync(timestamps);
1856
- reply.resolve();
1857
- });
1858
- data_channel_host.implement('onsignal', (reply, [data]) => {
1859
- const memory = alloc(data.length);
1860
- memory.view().set(data);
1861
- sfu_transport_proxy.onsignal(memory.pointer, memory.bytes);
1862
- memory.free();
1863
- reply.resolve();
1864
- });
1865
- data_channel_host.implement('ondata', (reply, [data, ccid, time]) => {
1866
- const memory = alloc(data.length);
1867
- memory.view().set(data);
1868
- sfu_transport_proxy.ondata(memory.pointer, memory.bytes, ccid, time, -1);
1869
- memory.free();
1870
- reply.resolve();
1871
- });
1872
- // setup cleanup
1873
- cleanup.unshift(() => {
1874
- data_channel.Leave();
1875
- data_channel.delete();
1876
- sfu_transport_proxy.delete();
1877
- });
1878
- data_channel_host.implement('open', (reply, [config]) => {
1879
- data_channel.Join(config);
1880
- reply.resolve();
1881
- });
1882
- data_channel_host.implement('datastream', (reply, [type = DataType.kRemoteControl, pendingListener]) => {
1883
- const listenerHost = channel.remote(pendingListener);
1884
- const data_stream = data_channel.CreateDataStream(type);
1885
- data_stream.on('ondata', (pointer, length, from) => {
1886
- const memory = view(pointer, length).slice();
1887
- listenerHost.make('ondata').transfer(memory.buffer).post(memory, from);
1888
- });
1889
- const data_stream_host = channel.receiver();
1890
- data_stream_host.implement('write', (reply, [data, dest, traits]) => {
1891
- const memory = alloc(data.length);
1892
- memory.view().set(data);
1893
- data_stream.Write(memory.pointer, memory.bytes, dest, traits);
1894
- memory.free();
1895
- reply.resolve();
1896
- });
1897
- data_stream_host.implement('subscribe', (reply, [request, remove]) => {
1898
- data_stream.Subscribe(request, remove);
1899
- reply.resolve();
1900
- });
1901
- data_stream_host.onbreak = () => data_stream.delete();
1902
- reply.resolve(`${data_stream_host}`);
1903
- });
1904
- data_channel_host.implement('subtitlestream', (reply, [type = DataType.kSubtitleRealtime, pendingListener]) => {
1905
- const subtitle = new native.SubtitleRealtime();
1906
- const listenerHost = channel.remote(pendingListener);
1907
- const data_stream = data_channel.CreateDataStream(type);
1908
- data_stream.on('ondata', (pointer, bytes, from) => {
1909
- subtitle.decode([pointer, bytes], (info) => {
1910
- listenerHost.make('ondata').post(info, from);
1911
- });
1912
- });
1913
- const data_stream_host = channel.receiver();
1914
- data_stream_host.implement('write', (reply, [data, dest]) => {
1915
- subtitle.encode(data, ([pointer, bytes]) => {
1916
- const traits = { direct: !!dest.length, merge: false };
1917
- data_stream.Write(pointer, bytes, dest, traits);
1918
- });
1919
- reply.resolve();
1920
- });
1921
- data_stream_host.implement('subscribe', (reply, [request, remove]) => {
1922
- data_stream.Subscribe(request, remove);
1923
- reply.resolve();
1924
- });
1925
- data_stream_host.onbreak = () => data_stream.delete();
1926
- reply.resolve(`${data_stream_host}`);
1927
- });
1928
- // cleanup
1929
- data_channel_host.onbreak = () => {
1930
- cleanup.forEach((v) => v());
1931
- cleanup.length = 0;
1932
- };
1933
- reply.resolve(`${data_channel_host}`);
1934
- });
1935
- setupBusyDetector();
1936
- // simple cpu overload detection
1937
- function setupBusyDetector() {
1938
- let last = Date.now();
1939
- let detectTimer;
1940
- const detectInterval = 1000;
1941
- const factor = 1.1;
1942
- const detect = () => {
1943
- const now = Date.now();
1944
- const delta = now - last;
1945
- const tester = detectInterval * factor;
1946
- if (delta > tester) {
1947
- console.log(`busy report:\n` +
1948
- `delta: ${delta}\n` +
1949
- `factor: ${factor}\n` +
1950
- `interval: ${detectInterval}\n` +
1951
- `delay: ${delta - detectInterval}\n`);
1952
- }
1953
- last = now;
1954
- detectTimer = setTimeout(detect, detectInterval);
1955
- };
1956
- detect();
1957
- return () => clearTimeout(detectTimer);
1958
- }
1959
-
1960
- }());