trtc-electron-sdk 10.0.100-beta.8 → 10.2.0-beta.0
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/liteav/Render/BGRAVideoRenderer/index.js +114 -0
- package/liteav/Render/Canvas3DRGBARenderer/index.js +13 -13
- package/liteav/Render/I420VideoRenderer/index.js +115 -0
- package/liteav/Render/RGBAVideoRenderer/index.js +115 -0
- package/liteav/Render/RGBRenderer/index.js +1 -1
- package/liteav/Render/index.d.ts +3 -0
- package/liteav/Render/index.js +6 -0
- package/liteav/Render/util.d.ts +13 -1
- package/liteav/Render/util.js +37 -2
- package/liteav/trtc.d.ts +25 -17
- package/liteav/trtc.js +298 -127
- package/liteav/trtc_define.d.ts +35 -9
- package/liteav/trtc_define.js +42 -13
- package/package.json +1 -1
- package/scripts/download.js +27 -0
- package/scripts/publish-doc.js +1 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const EventEmitter = require('events').EventEmitter;
|
|
13
|
+
const isEqual = require('lodash.isequal');
|
|
14
|
+
const { calcVideoStyle } = require('../util');
|
|
15
|
+
/* contentMode
|
|
16
|
+
* - 0: Cropped mode. Uniformly scale the video until it fills the visible boundaries (cropped).
|
|
17
|
+
* One dimension of the video may have clipped contents.
|
|
18
|
+
* - 1: Fit mode. Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit).
|
|
19
|
+
* Areas that are not filled due to the disparity in the aspect ratio will be filled with black.
|
|
20
|
+
*/
|
|
21
|
+
class BGRAVideoRenderer {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.cachedOptions = {};
|
|
24
|
+
this.event = new EventEmitter();
|
|
25
|
+
this.element = null;
|
|
26
|
+
this.video = document.createElement('video');
|
|
27
|
+
this.video.setAttribute('style', 'width: 100%; height: 100%; display: block; margin: 0 auto;');
|
|
28
|
+
this.video.setAttribute('autoplay', 'autoplay');
|
|
29
|
+
this.video.muted = true;
|
|
30
|
+
this.contentMode = 1;
|
|
31
|
+
this.ready = false;
|
|
32
|
+
this.track = new MediaStreamTrackGenerator({ kind: 'video' });
|
|
33
|
+
this.writer = this.track.writable.getWriter();
|
|
34
|
+
}
|
|
35
|
+
getView() {
|
|
36
|
+
return this.element;
|
|
37
|
+
}
|
|
38
|
+
_updateStyle(options = {
|
|
39
|
+
contentWidth: 0,
|
|
40
|
+
contentHeight: 0,
|
|
41
|
+
rotation: 0,
|
|
42
|
+
mirrorView: false,
|
|
43
|
+
contentMode: 0,
|
|
44
|
+
containerWidth: 0,
|
|
45
|
+
containerHeight: 0,
|
|
46
|
+
isNeedRotate: true
|
|
47
|
+
}) {
|
|
48
|
+
if (isEqual(this.cachedOptions, options)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.cachedOptions = Object.assign({}, options);
|
|
52
|
+
const style = calcVideoStyle(options);
|
|
53
|
+
Object.keys(style).forEach(key => {
|
|
54
|
+
this.video.style[key] = style[key];
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
drawFrame(frameData) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
if (!this.ready) {
|
|
60
|
+
this.ready = true;
|
|
61
|
+
this.event.emit('ready');
|
|
62
|
+
}
|
|
63
|
+
this._updateStyle({
|
|
64
|
+
rotation: frameData.rotation,
|
|
65
|
+
isNeedRotate: frameData.isNeedRotate,
|
|
66
|
+
contentWidth: frameData.width,
|
|
67
|
+
contentHeight: frameData.height,
|
|
68
|
+
contentMode: this.contentMode,
|
|
69
|
+
mirrorView: false,
|
|
70
|
+
containerWidth: this.element.clientWidth,
|
|
71
|
+
containerHeight: this.element.clientHeight,
|
|
72
|
+
});
|
|
73
|
+
if (global.bgraFrames) {
|
|
74
|
+
global.bgraFrames.push(frameData);
|
|
75
|
+
if (global.bgraFrames.length > 100) {
|
|
76
|
+
global.bgraFrames.shift();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
global.bgraFrames = [frameData];
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const vf = new VideoFrame(frameData.data, {
|
|
84
|
+
format: 'BGRA',
|
|
85
|
+
codedWidth: frameData.width,
|
|
86
|
+
codedHeight: frameData.height,
|
|
87
|
+
timestamp: frameData.timestamp,
|
|
88
|
+
});
|
|
89
|
+
yield this.writer.write(vf);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error('VideoRender.drawImage error:', error);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
bind(element) {
|
|
97
|
+
this.element = element;
|
|
98
|
+
if (this.element.firstChild) {
|
|
99
|
+
this.element.removeChild(this.element.firstChild);
|
|
100
|
+
}
|
|
101
|
+
this.element.appendChild(this.video);
|
|
102
|
+
this.video.srcObject = new MediaStream([this.track]);
|
|
103
|
+
}
|
|
104
|
+
unbind() {
|
|
105
|
+
if (this.element.firstChild) {
|
|
106
|
+
this.element.removeChild(this.element.firstChild);
|
|
107
|
+
}
|
|
108
|
+
this.element = null;
|
|
109
|
+
}
|
|
110
|
+
setContentMode(mode) {
|
|
111
|
+
this.contentMode = mode;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.default = BGRAVideoRenderer;
|
|
@@ -24,7 +24,7 @@ class Canvas3DRGBARenderer {
|
|
|
24
24
|
1, 1, 0.0,
|
|
25
25
|
-1, 1, 0.0
|
|
26
26
|
];
|
|
27
|
-
this.
|
|
27
|
+
this.vertexIndice = [
|
|
28
28
|
0, 1, 2,
|
|
29
29
|
0, 2, 3
|
|
30
30
|
];
|
|
@@ -37,7 +37,7 @@ class Canvas3DRGBARenderer {
|
|
|
37
37
|
}
|
|
38
38
|
_initGL() {
|
|
39
39
|
try {
|
|
40
|
-
this.gl = this.canvas.getContext('webgl', { alpha: true, premultipliedAlpha: false });
|
|
40
|
+
this.gl = this.canvas.getContext('webgl', { alpha: true, premultipliedAlpha: false }); //|| canvas.getContext("experimental-webgl", { antialias: false });
|
|
41
41
|
}
|
|
42
42
|
catch (e) {
|
|
43
43
|
return false;
|
|
@@ -103,21 +103,22 @@ class Canvas3DRGBARenderer {
|
|
|
103
103
|
_initTexture() {
|
|
104
104
|
this.texture = this.gl.createTexture();
|
|
105
105
|
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture);
|
|
106
|
-
//
|
|
106
|
+
// c++ addon 层拷贝数据时翻转,这里不做翻转
|
|
107
|
+
this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
107
108
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
108
109
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
109
110
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
110
111
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
111
112
|
}
|
|
112
|
-
|
|
113
|
+
_initTextureAttr() {
|
|
113
114
|
// vertex data
|
|
114
115
|
const vertexBuffer = this.gl.createBuffer();
|
|
115
116
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer);
|
|
116
117
|
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.vertex), this.gl.STATIC_DRAW);
|
|
117
|
-
//
|
|
118
|
-
const
|
|
119
|
-
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,
|
|
120
|
-
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this.
|
|
118
|
+
// indice data
|
|
119
|
+
const vertexIndiceBuffer = this.gl.createBuffer();
|
|
120
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, vertexIndiceBuffer);
|
|
121
|
+
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this.vertexIndice), this.gl.STATIC_DRAW);
|
|
121
122
|
// set position attribute
|
|
122
123
|
const aVertexPosition = this.gl.getAttribLocation(this.glProgram, 'aPos');
|
|
123
124
|
this.gl.vertexAttribPointer(aVertexPosition, 3, this.gl.FLOAT, false, 0, 0);
|
|
@@ -142,8 +143,7 @@ class Canvas3DRGBARenderer {
|
|
|
142
143
|
height: '100%',
|
|
143
144
|
display: 'flex',
|
|
144
145
|
justifyContent: 'center',
|
|
145
|
-
alignItems: 'center'
|
|
146
|
-
willChange: 'transform',
|
|
146
|
+
alignItems: 'center'
|
|
147
147
|
});
|
|
148
148
|
this.container = container;
|
|
149
149
|
element.appendChild(this.container);
|
|
@@ -169,7 +169,7 @@ class Canvas3DRGBARenderer {
|
|
|
169
169
|
}
|
|
170
170
|
} while (false);
|
|
171
171
|
if (ret) {
|
|
172
|
-
this.
|
|
172
|
+
this._initTextureAttr();
|
|
173
173
|
this._initTexture();
|
|
174
174
|
}
|
|
175
175
|
}
|
|
@@ -202,7 +202,7 @@ class Canvas3DRGBARenderer {
|
|
|
202
202
|
const { width, height, transform } = calcCanvasStyle(options);
|
|
203
203
|
this.canvas.width = width;
|
|
204
204
|
this.canvas.height = height;
|
|
205
|
-
this.canvas.style.transform =
|
|
205
|
+
this.canvas.style.transform = transform;
|
|
206
206
|
}
|
|
207
207
|
drawFrame(imageData) {
|
|
208
208
|
if (!this.ready) {
|
|
@@ -226,7 +226,7 @@ class Canvas3DRGBARenderer {
|
|
|
226
226
|
});
|
|
227
227
|
try {
|
|
228
228
|
this.gl.viewport(0, 0, contentWidth, contentHeight);
|
|
229
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, contentWidth, contentHeight, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, imageData.data //
|
|
229
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, contentWidth, contentHeight, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, imageData.data // new Uint8Array(imageData.data)
|
|
230
230
|
);
|
|
231
231
|
this.gl.drawElements(this.gl.TRIANGLES, 6, this.gl.UNSIGNED_SHORT, 0);
|
|
232
232
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const EventEmitter = require('events').EventEmitter;
|
|
13
|
+
const isEqual = require('lodash.isequal');
|
|
14
|
+
const { calcVideoStyle } = require('../util');
|
|
15
|
+
/* contentMode
|
|
16
|
+
* - 0: Cropped mode. Uniformly scale the video until it fills the visible boundaries (cropped).
|
|
17
|
+
* One dimension of the video may have clipped contents.
|
|
18
|
+
* - 1: Fit mode. Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit).
|
|
19
|
+
* Areas that are not filled due to the disparity in the aspect ratio will be filled with black.
|
|
20
|
+
*/
|
|
21
|
+
class I420VideoRenderer {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.cachedOptions = {};
|
|
24
|
+
this.event = new EventEmitter();
|
|
25
|
+
this.element = null;
|
|
26
|
+
this.video = document.createElement('video');
|
|
27
|
+
this.video.setAttribute('style', 'width: 100%; height: 100%; display: block; margin: 0 auto;');
|
|
28
|
+
this.video.setAttribute('autoplay', 'autoplay');
|
|
29
|
+
this.video.muted = true;
|
|
30
|
+
this.contentMode = 1;
|
|
31
|
+
this.ready = false;
|
|
32
|
+
this.track = new MediaStreamTrackGenerator({ kind: 'video' });
|
|
33
|
+
this.writer = this.track.writable.getWriter();
|
|
34
|
+
}
|
|
35
|
+
getView() {
|
|
36
|
+
return this.element;
|
|
37
|
+
}
|
|
38
|
+
_updateStyle(options = {
|
|
39
|
+
contentWidth: 0,
|
|
40
|
+
contentHeight: 0,
|
|
41
|
+
rotation: 0,
|
|
42
|
+
mirrorView: false,
|
|
43
|
+
contentMode: 0,
|
|
44
|
+
containerWidth: 0,
|
|
45
|
+
containerHeight: 0,
|
|
46
|
+
isNeedRotate: true
|
|
47
|
+
}) {
|
|
48
|
+
if (isEqual(this.cachedOptions, options)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.cachedOptions = Object.assign({}, options);
|
|
52
|
+
const style = calcVideoStyle(options);
|
|
53
|
+
Object.keys(style).forEach(key => {
|
|
54
|
+
this.video.style[key] = style[key];
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
drawFrame(frameData) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
if (!this.ready) {
|
|
60
|
+
this.ready = true;
|
|
61
|
+
this.event.emit('ready');
|
|
62
|
+
}
|
|
63
|
+
this._updateStyle({
|
|
64
|
+
rotation: frameData.rotation,
|
|
65
|
+
isNeedRotate: frameData.isNeedRotate,
|
|
66
|
+
contentWidth: frameData.width,
|
|
67
|
+
contentHeight: frameData.height,
|
|
68
|
+
contentMode: this.contentMode,
|
|
69
|
+
mirrorView: false,
|
|
70
|
+
containerWidth: this.element.clientWidth,
|
|
71
|
+
containerHeight: this.element.clientHeight,
|
|
72
|
+
});
|
|
73
|
+
if (global.i420Frames) {
|
|
74
|
+
global.i420Frames.push(frameData);
|
|
75
|
+
if (global.i420Frames.length > 100) {
|
|
76
|
+
global.i420Frames.shift();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
global.i420Frames = [frameData];
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const vf = new VideoFrame(frameData.data, {
|
|
84
|
+
format: 'I420',
|
|
85
|
+
codedWidth: frameData.width,
|
|
86
|
+
codedHeight: frameData.height,
|
|
87
|
+
timestamp: frameData.timestamp,
|
|
88
|
+
});
|
|
89
|
+
yield this.writer.write(vf);
|
|
90
|
+
// console.debug('VideoRender.drawImage write video frame success');
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('VideoRender.drawImage error:', error);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
bind(element) {
|
|
98
|
+
this.element = element;
|
|
99
|
+
if (this.element.firstChild) {
|
|
100
|
+
this.element.removeChild(this.element.firstChild);
|
|
101
|
+
}
|
|
102
|
+
this.element.appendChild(this.video);
|
|
103
|
+
this.video.srcObject = new MediaStream([this.track]);
|
|
104
|
+
}
|
|
105
|
+
unbind() {
|
|
106
|
+
if (this.element.firstChild) {
|
|
107
|
+
this.element.removeChild(this.element.firstChild);
|
|
108
|
+
}
|
|
109
|
+
this.element = null;
|
|
110
|
+
}
|
|
111
|
+
setContentMode(mode) {
|
|
112
|
+
this.contentMode = mode;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.default = I420VideoRenderer;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const EventEmitter = require('events').EventEmitter;
|
|
13
|
+
const isEqual = require('lodash.isequal');
|
|
14
|
+
const { calcVideoStyle } = require('../util');
|
|
15
|
+
/* contentMode
|
|
16
|
+
* - 0: Cropped mode. Uniformly scale the video until it fills the visible boundaries (cropped).
|
|
17
|
+
* One dimension of the video may have clipped contents.
|
|
18
|
+
* - 1: Fit mode. Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit).
|
|
19
|
+
* Areas that are not filled due to the disparity in the aspect ratio will be filled with black.
|
|
20
|
+
*/
|
|
21
|
+
class RGBAVideoRenderer {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.cachedOptions = {};
|
|
24
|
+
this.event = new EventEmitter();
|
|
25
|
+
this.element = null;
|
|
26
|
+
this.video = document.createElement('video');
|
|
27
|
+
this.video.setAttribute('style', 'width: 100%; height: 100%; display: block; margin: 0 auto;');
|
|
28
|
+
this.video.setAttribute('autoplay', 'autoplay');
|
|
29
|
+
this.video.muted = true;
|
|
30
|
+
this.contentMode = 1;
|
|
31
|
+
this.ready = false;
|
|
32
|
+
this.track = new MediaStreamTrackGenerator({ kind: 'video' });
|
|
33
|
+
this.writer = this.track.writable.getWriter();
|
|
34
|
+
}
|
|
35
|
+
getView() {
|
|
36
|
+
return this.element;
|
|
37
|
+
}
|
|
38
|
+
_updateStyle(options = {
|
|
39
|
+
contentWidth: 0,
|
|
40
|
+
contentHeight: 0,
|
|
41
|
+
rotation: 0,
|
|
42
|
+
mirrorView: false,
|
|
43
|
+
contentMode: 0,
|
|
44
|
+
containerWidth: 0,
|
|
45
|
+
containerHeight: 0,
|
|
46
|
+
isNeedRotate: true
|
|
47
|
+
}) {
|
|
48
|
+
if (isEqual(this.cachedOptions, options)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.cachedOptions = Object.assign({}, options);
|
|
52
|
+
const style = calcVideoStyle(options);
|
|
53
|
+
Object.keys(style).forEach(key => {
|
|
54
|
+
this.video.style[key] = style[key];
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
drawFrame(frameData) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
if (!this.ready) {
|
|
60
|
+
this.ready = true;
|
|
61
|
+
this.event.emit('ready');
|
|
62
|
+
}
|
|
63
|
+
this._updateStyle({
|
|
64
|
+
rotation: frameData.rotation,
|
|
65
|
+
isNeedRotate: frameData.isNeedRotate,
|
|
66
|
+
contentWidth: frameData.width,
|
|
67
|
+
contentHeight: frameData.height,
|
|
68
|
+
contentMode: this.contentMode,
|
|
69
|
+
mirrorView: false,
|
|
70
|
+
containerWidth: this.element.clientWidth,
|
|
71
|
+
containerHeight: this.element.clientHeight,
|
|
72
|
+
});
|
|
73
|
+
if (global.rgbaFrames) {
|
|
74
|
+
global.rgbaFrames.push(frameData);
|
|
75
|
+
if (global.rgbaFrames.length > 100) {
|
|
76
|
+
global.rgbaFrames.shift();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
global.rgbaFrames = [frameData];
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const vf = new VideoFrame(frameData.data, {
|
|
84
|
+
format: 'RGBA',
|
|
85
|
+
codedWidth: frameData.width,
|
|
86
|
+
codedHeight: frameData.height,
|
|
87
|
+
timestamp: frameData.timestamp,
|
|
88
|
+
});
|
|
89
|
+
yield this.writer.write(vf);
|
|
90
|
+
// console.debug('VideoRender.drawImage write video frame success');
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('VideoRender.drawImage error:', error);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
bind(element) {
|
|
98
|
+
this.element = element;
|
|
99
|
+
if (this.element.firstChild) {
|
|
100
|
+
this.element.removeChild(this.element.firstChild);
|
|
101
|
+
}
|
|
102
|
+
this.element.appendChild(this.video);
|
|
103
|
+
this.video.srcObject = new MediaStream([this.track]);
|
|
104
|
+
}
|
|
105
|
+
unbind() {
|
|
106
|
+
if (this.element.firstChild) {
|
|
107
|
+
this.element.removeChild(this.element.firstChild);
|
|
108
|
+
}
|
|
109
|
+
this.element = null;
|
|
110
|
+
}
|
|
111
|
+
setContentMode(mode) {
|
|
112
|
+
this.contentMode = mode;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.default = RGBAVideoRenderer;
|
|
@@ -92,7 +92,7 @@ class RGBRenderer {
|
|
|
92
92
|
containerHeight: this.container.clientHeight,
|
|
93
93
|
isNeedRotate
|
|
94
94
|
});
|
|
95
|
-
let newImage = new ImageData(new Uint8ClampedArray(imageData.data.
|
|
95
|
+
let newImage = new ImageData(new Uint8ClampedArray(imageData.data.buffer || imageData.data), width, height);
|
|
96
96
|
const tempCanvas = document.createElement('canvas');
|
|
97
97
|
tempCanvas.width = imageData.width;
|
|
98
98
|
tempCanvas.height = imageData.height;
|
package/liteav/Render/index.d.ts
CHANGED
package/liteav/Render/index.js
CHANGED
|
@@ -9,6 +9,9 @@ const GlRenderer_1 = __importDefault(require("./GlRenderer"));
|
|
|
9
9
|
const SoftwareRenderer_1 = __importDefault(require("./SoftwareRenderer"));
|
|
10
10
|
// @ts-ignore
|
|
11
11
|
const RGBRenderer_1 = __importDefault(require("./RGBRenderer"));
|
|
12
|
+
const I420VideoRenderer_1 = __importDefault(require("./I420VideoRenderer"));
|
|
13
|
+
const BGRAVideoRenderer_1 = __importDefault(require("./BGRAVideoRenderer"));
|
|
14
|
+
const RGBAVideoRenderer_1 = __importDefault(require("./RGBAVideoRenderer"));
|
|
12
15
|
const Canvas3DRGBARenderer_1 = __importDefault(require("./Canvas3DRGBARenderer"));
|
|
13
16
|
class GlRenderer {
|
|
14
17
|
constructor() {
|
|
@@ -53,5 +56,8 @@ exports.default = {
|
|
|
53
56
|
GlRenderer,
|
|
54
57
|
SoftwareRenderer: SoftwareRenderer_1.default,
|
|
55
58
|
RGBRenderer: RGBRenderer_1.default,
|
|
59
|
+
I420VideoRenderer: I420VideoRenderer_1.default,
|
|
60
|
+
BGRAVideoRenderer: BGRAVideoRenderer_1.default,
|
|
61
|
+
RGBAVideoRenderer: RGBAVideoRenderer_1.default,
|
|
56
62
|
Canvas3DRGBARenderer: Canvas3DRGBARenderer_1.default,
|
|
57
63
|
};
|
package/liteav/Render/util.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ export declare class Config {
|
|
|
16
16
|
setDebugMode(enable: boolean): void;
|
|
17
17
|
getDebugMode(): boolean;
|
|
18
18
|
}
|
|
19
|
-
export declare const config: Config;
|
|
20
19
|
export declare function isNeedKeepWidthAndHeight(rotation: number, isNeedRotate: boolean): boolean;
|
|
21
20
|
export declare function calcScaleRate(vertical: boolean, contentMode: number, contentWidth: number, contentHeight: number, containerWidth: number, containerHeight: number): number;
|
|
22
21
|
export declare function calcCanvasStyle(options?: {
|
|
@@ -31,4 +30,17 @@ export declare function calcCanvasStyle(options?: {
|
|
|
31
30
|
}): {
|
|
32
31
|
[x: string]: any;
|
|
33
32
|
};
|
|
33
|
+
export declare function calcVideoStyle(options?: {
|
|
34
|
+
contentWidth: number;
|
|
35
|
+
contentHeight: number;
|
|
36
|
+
rotation: number;
|
|
37
|
+
mirrorView: boolean;
|
|
38
|
+
contentMode: number;
|
|
39
|
+
containerWidth: number;
|
|
40
|
+
containerHeight: number;
|
|
41
|
+
isNeedRotate: boolean;
|
|
42
|
+
}): {
|
|
43
|
+
[x: string]: any;
|
|
44
|
+
};
|
|
45
|
+
export declare const config: Config;
|
|
34
46
|
export declare function allocBuffer(length: number, userId?: string, streamType?: TRTCVideoStreamType): Buffer;
|
package/liteav/Render/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.allocBuffer = exports.
|
|
3
|
+
exports.allocBuffer = exports.config = exports.calcVideoStyle = exports.calcCanvasStyle = exports.calcScaleRate = exports.isNeedKeepWidthAndHeight = exports.Config = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* 配置对象, 可用来打开 debug 模式
|
|
6
6
|
*
|
|
@@ -23,7 +23,6 @@ class Config {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
exports.Config = Config;
|
|
26
|
-
exports.config = new Config();
|
|
27
26
|
function isNeedKeepWidthAndHeight(rotation, isNeedRotate) {
|
|
28
27
|
// 需保持宽高不做变化
|
|
29
28
|
return rotation === 0 || rotation === 180 || !isNeedRotate;
|
|
@@ -92,6 +91,42 @@ function calcCanvasStyle(options = {
|
|
|
92
91
|
return style;
|
|
93
92
|
}
|
|
94
93
|
exports.calcCanvasStyle = calcCanvasStyle;
|
|
94
|
+
function calcVideoStyle(options = {
|
|
95
|
+
contentWidth: 0,
|
|
96
|
+
contentHeight: 0,
|
|
97
|
+
rotation: 0,
|
|
98
|
+
mirrorView: false,
|
|
99
|
+
contentMode: 0,
|
|
100
|
+
containerWidth: 0,
|
|
101
|
+
containerHeight: 0,
|
|
102
|
+
isNeedRotate: true
|
|
103
|
+
}) {
|
|
104
|
+
if ([0, 90, 180, 270].indexOf(options.rotation) === -1) {
|
|
105
|
+
throw new Error('Invalid value for rotation. Only support 0, 90, 180, 270');
|
|
106
|
+
}
|
|
107
|
+
let width = 0;
|
|
108
|
+
let height = 0;
|
|
109
|
+
const isKeepWidthHeight = isNeedKeepWidthAndHeight(options.rotation, options.isNeedRotate);
|
|
110
|
+
if (isNeedKeepWidthAndHeight(options.rotation, options.isNeedRotate)) {
|
|
111
|
+
width = options.contentWidth;
|
|
112
|
+
height = options.contentHeight;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
height = options.contentWidth;
|
|
116
|
+
width = options.contentHeight;
|
|
117
|
+
}
|
|
118
|
+
const scale = calcScaleRate(!isKeepWidthHeight, options.contentMode, width, height, options.containerWidth, options.containerHeight);
|
|
119
|
+
const style = {
|
|
120
|
+
width: `${width * scale}px`,
|
|
121
|
+
height: `${height * scale}px`,
|
|
122
|
+
};
|
|
123
|
+
if (options.mirrorView) {
|
|
124
|
+
style.transform = 'rotateY(180deg)';
|
|
125
|
+
}
|
|
126
|
+
return style;
|
|
127
|
+
}
|
|
128
|
+
exports.calcVideoStyle = calcVideoStyle;
|
|
129
|
+
exports.config = new Config();
|
|
95
130
|
function allocBuffer(length, userId, streamType) {
|
|
96
131
|
console.debug('trtc:alloc buffer:', length, userId, streamType);
|
|
97
132
|
if (length >= 1) {
|
package/liteav/trtc.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
-
import { AudioMusicParam, Rect, TRTCAppScene, TRTCAudioEffectParam, TRTCAudioQuality, TRTCBeautyStyle, TRTCDeviceState, TRTCDeviceType, TRTCLogLevel, TRTCRenderParams, TRTCRoleType, TRTCSwitchRoomParam, TRTCVideoBufferType, TRTCVideoFillMode, TRTCVideoFrame, TRTCVideoPixelFormat, TRTCVideoRotation, TRTCVideoStreamType, TRTCWaterMarkSrcType, PluginInfo, TRTCAudioRecordingParams, TRTCScreenCaptureSourceInfo, TRTCScreenCaptureProperty } from './trtc_define';
|
|
3
|
+
import { AudioMusicParam, Rect, TRTCAppScene, TRTCAudioEffectParam, TRTCAudioQuality, TRTCBeautyStyle, TRTCDeviceState, TRTCDeviceType, TRTCLogLevel, TRTCRenderParams, TRTCRoleType, TRTCSwitchRoomParam, TRTCVideoBufferType, TRTCVideoFillMode, TRTCVideoFrame, TRTCVideoPixelFormat, TRTCVideoRotation, TRTCVideoStreamType, TRTCWaterMarkSrcType, PluginInfo, TRTCAudioRecordingParams, TRTCScreenCaptureSourceInfo, TRTCScreenCaptureProperty, TRTCSpeedTestParams } from './trtc_define';
|
|
4
4
|
export * from './trtc_define';
|
|
5
5
|
export * from './trtc_code';
|
|
6
6
|
/**
|
|
@@ -337,6 +337,15 @@ declare class TRTCCloud extends EventEmitter {
|
|
|
337
337
|
* @param {Number} totalCount - 需要测速的服务器总数量
|
|
338
338
|
*/
|
|
339
339
|
bindOnSpeedTest(): void;
|
|
340
|
+
/**
|
|
341
|
+
* 5.5 网速测试的结果回调
|
|
342
|
+
*
|
|
343
|
+
* 该统计回调由 startSpeedTest 触发。
|
|
344
|
+
*
|
|
345
|
+
* @event TRTCCallback#onSpeedTestResult
|
|
346
|
+
* @param {TRTCSpeedTestResult} result 网速测试数据数据,包括丢包、往返延迟、上下行的带宽速率。
|
|
347
|
+
*/
|
|
348
|
+
bindOnSpeedTestResult(): void;
|
|
340
349
|
/**
|
|
341
350
|
* 6.1 摄像头准备就绪
|
|
342
351
|
*
|
|
@@ -1787,13 +1796,6 @@ declare class TRTCCloud extends EventEmitter {
|
|
|
1787
1796
|
* @param {Number} volume - 音量大小,100为正常音量,取值范围为0 - 100;默认值:100
|
|
1788
1797
|
*/
|
|
1789
1798
|
setMusicPublishVolume(id: number, volume: number): void;
|
|
1790
|
-
/**
|
|
1791
|
-
* 11.22 调整背景音乐的变速效果
|
|
1792
|
-
*
|
|
1793
|
-
* @param {Number} id - 音乐 ID
|
|
1794
|
-
* @param {Number} speedRate - 速度,默认值是1.0f,范围是:[0.5 ~ 2] 之间的浮点数;
|
|
1795
|
-
*/
|
|
1796
|
-
setMusicSpeedRate(id: number, speedRate: number): void;
|
|
1797
1799
|
/**
|
|
1798
1800
|
* 12.1 废弃接口: 播放音效
|
|
1799
1801
|
*
|
|
@@ -1864,13 +1866,21 @@ declare class TRTCCloud extends EventEmitter {
|
|
|
1864
1866
|
* 测速结果将会用于优化 SDK 接下来的服务器选择策略,因此推荐您在用户首次通话前先进行一次测速,这将有助于我们选择最佳的服务器。
|
|
1865
1867
|
* 同时,如果测试结果非常不理想,您可以通过醒目的 UI 提示用户选择更好的网络。
|
|
1866
1868
|
*
|
|
1867
|
-
*
|
|
1869
|
+
* 注意:
|
|
1870
|
+
* 1. 测速过程将产生少量的基础服务费用,详见 [计费概述 > 基础服务](https://cloud.tencent.com/document/product/647/17157#.E5.9F.BA.E7.A1.80.E6.9C.8D.E5.8A.A1) 文档说明。
|
|
1871
|
+
* 2. 请在进入房间前进行网速测试,在房间中网速测试会影响正常的音视频传输效果,而且由于干扰过多,网速测试结果也不准确。
|
|
1872
|
+
* 3. 同一时间只允许一项网速测试任务运行。
|
|
1873
|
+
*
|
|
1874
|
+
* @param {TRTCSpeedTestParams} params - 测速参数
|
|
1875
|
+
* @param {Number} params.sdkAppId - 应用标识
|
|
1876
|
+
* @param {String} params.userId - 用户标识
|
|
1877
|
+
* @param {String} params.userSig - 用户签名
|
|
1878
|
+
* @param {Number} params.expectedUpBandwidth - 预期的上行带宽(kbps,取值范围: 10 ~ 5000,为 0 时不测试)。
|
|
1879
|
+
* @param {Number} params.expectedDownBandwidth - 预期的下行带宽(kbps,取值范围: 10 ~ 5000,为 0 时不测试)。
|
|
1868
1880
|
*
|
|
1869
|
-
* @
|
|
1870
|
-
* @param {String} userId - 用户标识
|
|
1871
|
-
* @param {String} userSig - 用户签名
|
|
1881
|
+
* @return 接口调用结果,< 0:失败
|
|
1872
1882
|
*/
|
|
1873
|
-
startSpeedTest(
|
|
1883
|
+
startSpeedTest(params: TRTCSpeedTestParams | number, userId?: string, userSig?: string): any;
|
|
1874
1884
|
/**
|
|
1875
1885
|
* 13.2 停止网络测速
|
|
1876
1886
|
*/
|
|
@@ -1986,10 +1996,8 @@ declare class TRTCCloud extends EventEmitter {
|
|
|
1986
1996
|
/**
|
|
1987
1997
|
* 选择绘制的模式 (webgl/yuvcanvs/)
|
|
1988
1998
|
* @param {Number} mode -
|
|
1989
|
-
* - 1
|
|
1990
|
-
* - 2
|
|
1991
|
-
* - 3 RGBA Canvas 2D
|
|
1992
|
-
* - 4 RGBA WebGL
|
|
1999
|
+
* - 1 webgl
|
|
2000
|
+
* - 2 yuvcanvs
|
|
1993
2001
|
*/
|
|
1994
2002
|
setRenderMode(mode?: number): void;
|
|
1995
2003
|
initPluginManager(): void;
|