zego-express-engine-electron-plugin-blend-image-private 1.2.8
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/ZegoExpressWebgl.js +738 -0
- package/index.d.ts +521 -0
- package/index.js +537 -0
- package/mac/ZegoBlendImageNode.node +0 -0
- package/mac/ZegoBlendImageNode.node.dSYM/Contents/Info.plist +20 -0
- package/mac/ZegoBlendImageNode.node.dSYM/Contents/Resources/DWARF/ZegoBlendImageNode.node +0 -0
- package/mac/libZegoScreenCaptureOSX.dylib +0 -0
- package/package.json +20 -0
- package/win/x64/ZegoBlendImageNode.node +0 -0
- package/win/x64/ZegoBlendImageNode.pdb +0 -0
- package/win/x64/ZegoScreenCapture.dll +0 -0
- package/win/x86/ZegoBlendImageNode.node +0 -0
- package/win/x86/ZegoBlendImageNode.pdb +0 -0
- package/win/x86/ZegoScreenCapture.dll +0 -0
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
function Canvas2dRender() {
|
|
2
|
+
this.canvas = null //view
|
|
3
|
+
this.localCanvasConfig = {} //the local rendering configuration
|
|
4
|
+
this.flipMode = 0
|
|
5
|
+
this.imageData = null
|
|
6
|
+
this.render = null //draw context
|
|
7
|
+
this.viewMode = 0
|
|
8
|
+
this.w = void 0
|
|
9
|
+
this.h = void 0
|
|
10
|
+
|
|
11
|
+
//save view port data
|
|
12
|
+
this.prevViewPort = { w: 0, h: 0, canvasW: 0, canvasH: 0 }
|
|
13
|
+
|
|
14
|
+
//current view port
|
|
15
|
+
this.CurrentViewPort = { start_x: 0, start_y: 0, dataWidth: 0, dataHeight: 0 }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Canvas2dRender.prototype = {
|
|
19
|
+
setViewMode(mode) {
|
|
20
|
+
this.viewMode = mode
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
setCurrentViewPort(start_x, start_y, dataWidth, dataHeight) {
|
|
24
|
+
this.CurrentViewPort.start_x = start_x
|
|
25
|
+
this.CurrentViewPort.start_y = start_y
|
|
26
|
+
this.CurrentViewPort.dataWidth = dataWidth
|
|
27
|
+
this.CurrentViewPort.dataHeight = dataHeight
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
bindCanvas(canvas) {
|
|
31
|
+
this.canvas = canvas
|
|
32
|
+
//create canvas context
|
|
33
|
+
this.render = this.canvas.getContext('2d')
|
|
34
|
+
return null != this.render
|
|
35
|
+
},
|
|
36
|
+
unbindCanvas() {
|
|
37
|
+
this.observer && this.observer.unobserve && this.observer.disconnect()
|
|
38
|
+
this.render = null
|
|
39
|
+
this.canvas = null
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
calcViewPortMode1() {
|
|
43
|
+
const { w, h, prevViewPort } = this
|
|
44
|
+
|
|
45
|
+
if (w && h && this.canvas && this.render) {
|
|
46
|
+
const rect = this.canvas.getBoundingClientRect()
|
|
47
|
+
const canvasH = rect.height
|
|
48
|
+
const canvasW = rect.width
|
|
49
|
+
if (!(canvasW && canvasH)) return
|
|
50
|
+
const isSame =
|
|
51
|
+
w === prevViewPort.w &&
|
|
52
|
+
h === prevViewPort.h &&
|
|
53
|
+
canvasW === prevViewPort.canvasW &&
|
|
54
|
+
canvasH === prevViewPort.canvasH
|
|
55
|
+
|
|
56
|
+
let newW
|
|
57
|
+
let newH
|
|
58
|
+
const ratioW = w / canvasW
|
|
59
|
+
const ratioH = h / canvasH
|
|
60
|
+
|
|
61
|
+
if (this.viewMode === 1) {
|
|
62
|
+
if (ratioW > ratioH) {
|
|
63
|
+
newH = canvasH
|
|
64
|
+
newW = (w * canvasH) / h
|
|
65
|
+
} else {
|
|
66
|
+
newW = canvasW
|
|
67
|
+
newH = (h * canvasW) / w
|
|
68
|
+
}
|
|
69
|
+
const dpr = window.devicePixelRatio
|
|
70
|
+
var offsetX = -(newW - canvasW) / 2
|
|
71
|
+
var offsetY = -(newH - canvasH) / 2
|
|
72
|
+
if (dpr !== 1) {
|
|
73
|
+
newW = newW * dpr
|
|
74
|
+
newH = newH * dpr
|
|
75
|
+
offsetX = offsetX * dpr
|
|
76
|
+
offsetY = offsetY * dpr
|
|
77
|
+
}
|
|
78
|
+
Object.assign(prevViewPort, { w, h, canvasW, canvasH, offsetX, offsetY, newW, newH })
|
|
79
|
+
|
|
80
|
+
if ((offsetX, offsetY, newW, newH)) {
|
|
81
|
+
var start_x = offsetX
|
|
82
|
+
var start_y = offsetY
|
|
83
|
+
var dataWidth = newW
|
|
84
|
+
var dataHeight = newH
|
|
85
|
+
|
|
86
|
+
this.setCurrentViewPort(start_x, start_y, dataWidth, dataHeight)
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
const dpr = window.devicePixelRatio
|
|
90
|
+
var realCanvasH = canvasH
|
|
91
|
+
var realCanvasW = canvasW
|
|
92
|
+
if (dpr !== 1) {
|
|
93
|
+
realCanvasW = realCanvasW * dpr
|
|
94
|
+
realCanvasH = realCanvasH * dpr
|
|
95
|
+
}
|
|
96
|
+
Object.assign(prevViewPort, {
|
|
97
|
+
w,
|
|
98
|
+
h,
|
|
99
|
+
realCanvasW,
|
|
100
|
+
realCanvasH,
|
|
101
|
+
offsetX: 0,
|
|
102
|
+
offsetY: 0,
|
|
103
|
+
newW: realCanvasW,
|
|
104
|
+
newH: realCanvasH,
|
|
105
|
+
})
|
|
106
|
+
if ((realCanvasW, realCanvasH)) {
|
|
107
|
+
var start_x = 0
|
|
108
|
+
var start_y = 0
|
|
109
|
+
var dataWidth = realCanvasW
|
|
110
|
+
var dataHeight = realCanvasH
|
|
111
|
+
this.setCurrentViewPort(start_x, start_y, dataWidth, dataHeight)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
calcViewPortMode2(canvas_w, canvas_h) {
|
|
118
|
+
const { w, h } = this
|
|
119
|
+
let dataWidth = 0,
|
|
120
|
+
dataHeight = 0
|
|
121
|
+
if (w < canvas_w && h < canvas_h) {
|
|
122
|
+
const scale_w = ((canvas_w - w) / canvas_w) * 1.0
|
|
123
|
+
const scale_h = ((canvas_h - h) / canvas_h) * 1.0
|
|
124
|
+
if (scale_w < scale_h) {
|
|
125
|
+
dataWidth = canvas_w
|
|
126
|
+
dataHeight = ((canvas_w - w) / w) * 1.0 * h + h
|
|
127
|
+
var start_x = 0
|
|
128
|
+
var start_Y = (canvas_h - dataHeight) / 2.0
|
|
129
|
+
this.setCurrentViewPort(start_x, start_Y, dataWidth, dataHeight)
|
|
130
|
+
} else {
|
|
131
|
+
dataHeight = canvas_h
|
|
132
|
+
dataWidth = ((canvas_h - h) / h) * 1.0 * w + w
|
|
133
|
+
var start_x = canvas_w / 2.0 - dataWidth / 2.0
|
|
134
|
+
var start_Y = 0
|
|
135
|
+
this.setCurrentViewPort(start_x, start_Y, dataWidth, dataHeight)
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
const scale_w = ((w - canvas_w) / w) * 1.0
|
|
139
|
+
const scale_h = ((h - canvas_h) / h) * 1.0
|
|
140
|
+
if (scale_w < scale_h) {
|
|
141
|
+
dataHeight = canvas_h
|
|
142
|
+
dataWidth = w - ((h - canvas_h) / h) * 1.0 * w
|
|
143
|
+
var start_x = canvas_w / 2.0 - dataWidth / 2.0
|
|
144
|
+
var start_Y = 0
|
|
145
|
+
this.setCurrentViewPort(start_x, start_Y, dataWidth, dataHeight)
|
|
146
|
+
} else {
|
|
147
|
+
dataWidth = canvas_w
|
|
148
|
+
dataHeight = h - ((w - canvas_w) / w) * 1.0 * h
|
|
149
|
+
var start_x = 0
|
|
150
|
+
var start_Y = canvas_h / 2.0 - dataHeight / 2.0
|
|
151
|
+
this.setCurrentViewPort(start_x, start_Y, dataWidth, dataHeight)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
setFlipMode(flipMode) {
|
|
157
|
+
if (this.flipMode === flipMode) {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
this.flipMode = flipMode
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
updataSize(canvas) {
|
|
164
|
+
const dpr = window.devicePixelRatio
|
|
165
|
+
|
|
166
|
+
const { width, height } = canvas.getBoundingClientRect()
|
|
167
|
+
const displayWidth = Math.round(width * dpr)
|
|
168
|
+
const displayHeight = Math.round(height * dpr)
|
|
169
|
+
|
|
170
|
+
// Check if the canvas is not the same size.
|
|
171
|
+
const needResize = canvas.width != displayWidth || canvas.height != displayHeight
|
|
172
|
+
|
|
173
|
+
if (needResize) {
|
|
174
|
+
// Make the canvas the same size
|
|
175
|
+
canvas.width = displayWidth
|
|
176
|
+
canvas.height = displayHeight
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
updateCanvas(
|
|
181
|
+
config = {
|
|
182
|
+
width: 0,
|
|
183
|
+
height: 0,
|
|
184
|
+
rotation: 0,
|
|
185
|
+
mirrorView: false,
|
|
186
|
+
clientWidth: 0,
|
|
187
|
+
clientHeight: 0,
|
|
188
|
+
contentWidth,
|
|
189
|
+
contentHeight,
|
|
190
|
+
},
|
|
191
|
+
isUseLocal = true
|
|
192
|
+
) {
|
|
193
|
+
// check if display options changed
|
|
194
|
+
/*if (isUseLocal && IsEqual(config, this.localCanvasConfig)) {
|
|
195
|
+
return;
|
|
196
|
+
}*/
|
|
197
|
+
this.localCanvasConfig = config
|
|
198
|
+
|
|
199
|
+
let transformItems = []
|
|
200
|
+
transformItems.push(`rotateZ(${config.rotation}deg)`)
|
|
201
|
+
|
|
202
|
+
// check for mirror
|
|
203
|
+
if (config.mirrorView) {
|
|
204
|
+
transformItems.push('rotateY(180deg)')
|
|
205
|
+
}
|
|
206
|
+
if (transformItems.length > 0) {
|
|
207
|
+
let transform = `${transformItems.join(' ')}`
|
|
208
|
+
this.canvas.style.transform = transform
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
drawFrame(imageData = { databuffer, width, height }) {
|
|
212
|
+
this.w = imageData.width
|
|
213
|
+
this.h = imageData.height
|
|
214
|
+
|
|
215
|
+
//Adapt to the width and height of the dpr canvas
|
|
216
|
+
this.updataSize(this.canvas)
|
|
217
|
+
|
|
218
|
+
//Because the data is flipped as it passes, it needs to be corrected
|
|
219
|
+
let mirror = false
|
|
220
|
+
let rotation = 180
|
|
221
|
+
if (this.flipMode == 0) {
|
|
222
|
+
mirror = true
|
|
223
|
+
} else {
|
|
224
|
+
//custom data
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let contentWidth = imageData.width
|
|
228
|
+
let contentHeight = imageData.height
|
|
229
|
+
this.updateCanvas({
|
|
230
|
+
width: this.canvas.width,
|
|
231
|
+
height: this.canvas.height,
|
|
232
|
+
rotation,
|
|
233
|
+
mirrorView: mirror,
|
|
234
|
+
clientWidth: this.canvas.width,
|
|
235
|
+
clientHeight: this.canvas.height,
|
|
236
|
+
contentWidth,
|
|
237
|
+
contentHeight,
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
//Calc viewport
|
|
241
|
+
if (this.viewMode != 0) {
|
|
242
|
+
this.calcViewPortMode1()
|
|
243
|
+
} else {
|
|
244
|
+
const canvas_w = this.canvas.width
|
|
245
|
+
const canvas_h = this.canvas.height
|
|
246
|
+
this.calcViewPortMode2(canvas_w, canvas_h)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
//draw
|
|
250
|
+
let buffer = {
|
|
251
|
+
data: imageData.databuffer,
|
|
252
|
+
width: imageData.width,
|
|
253
|
+
height: imageData.height,
|
|
254
|
+
displayWidth: this.canvas.width,
|
|
255
|
+
displayHeight: this.canvas.height,
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/*if (this.canvas.width != buffer.displayWidth || this.canvas.height != buffer.displayHeight) {
|
|
259
|
+
// Keep the canvas at the right size...
|
|
260
|
+
|
|
261
|
+
this.canvas.width = buffer.displayWidth;
|
|
262
|
+
this.canvas.height = buffer.displayHeight;
|
|
263
|
+
}*/
|
|
264
|
+
|
|
265
|
+
//set background color
|
|
266
|
+
this.canvas.style.backgroundColor = 'black'
|
|
267
|
+
|
|
268
|
+
if (
|
|
269
|
+
this.imageData === null ||
|
|
270
|
+
this.imageData.width != buffer.width ||
|
|
271
|
+
this.imageData.height != buffer.height
|
|
272
|
+
) {
|
|
273
|
+
this.imageData = this.render.createImageData(buffer.width, buffer.height)
|
|
274
|
+
this.render.clearRect(0, 0, this.canvas.width, this.canvas.height) //当视频源宽高比例发生变化时需要清空画布,不然会出现上一帧的残留
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
for (var i = 0; i < this.imageData.data.length; i += 4) {
|
|
278
|
+
this.imageData.data[i + 0] = buffer.data[i + 0]
|
|
279
|
+
this.imageData.data[i + 1] = buffer.data[i + 1]
|
|
280
|
+
this.imageData.data[i + 2] = buffer.data[i + 2]
|
|
281
|
+
this.imageData.data[i + 3] = buffer.data[i + 3]
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
//temp canvas: put data to this temp canvas
|
|
285
|
+
var resampleCanvas = document.createElement('canvas')
|
|
286
|
+
resampleCanvas.width = buffer.width
|
|
287
|
+
resampleCanvas.height = buffer.height
|
|
288
|
+
var resampleContext = resampleCanvas.getContext('2d')
|
|
289
|
+
|
|
290
|
+
//the width and height of the view port
|
|
291
|
+
let new_w = this.CurrentViewPort.dataWidth
|
|
292
|
+
let new_h = this.CurrentViewPort.dataHeight
|
|
293
|
+
//the start point of the view port
|
|
294
|
+
let viewportx = this.CurrentViewPort.start_x
|
|
295
|
+
let viewporty = this.CurrentViewPort.start_y
|
|
296
|
+
|
|
297
|
+
resampleContext.putImageData(this.imageData, 0, 0, 0, 0, buffer.width, buffer.height)
|
|
298
|
+
|
|
299
|
+
this.render.drawImage(
|
|
300
|
+
resampleCanvas,
|
|
301
|
+
0,
|
|
302
|
+
0,
|
|
303
|
+
buffer.width,
|
|
304
|
+
buffer.height,
|
|
305
|
+
viewportx,
|
|
306
|
+
viewporty,
|
|
307
|
+
new_w,
|
|
308
|
+
new_h
|
|
309
|
+
)
|
|
310
|
+
},
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function WebGLRender() {
|
|
314
|
+
this.gl = null
|
|
315
|
+
this.render2d = null
|
|
316
|
+
this.glProgram = null
|
|
317
|
+
this.vertexBuffer = null
|
|
318
|
+
this.vertexIndiceBuffer = null
|
|
319
|
+
this.samplerUniform = null
|
|
320
|
+
this.vShader = null
|
|
321
|
+
this.fShader = null
|
|
322
|
+
this.haveInit = false
|
|
323
|
+
this.texture = null
|
|
324
|
+
this.canvas = null
|
|
325
|
+
this.pbo = null
|
|
326
|
+
this.cur_width = 0
|
|
327
|
+
this.cur_height = 0
|
|
328
|
+
this.w = void 0
|
|
329
|
+
this.h = void 0
|
|
330
|
+
this.viewMode = 0
|
|
331
|
+
this.flipMode = null
|
|
332
|
+
this.bkColor = null
|
|
333
|
+
this.setbkColor = false
|
|
334
|
+
this.bkAlpha = 0.0
|
|
335
|
+
this.bkRed = 0.0
|
|
336
|
+
this.bkGreen = 0.0
|
|
337
|
+
this.bkBlue = 0.0
|
|
338
|
+
this.preserveDrawingBuffer = false
|
|
339
|
+
|
|
340
|
+
this.vertex = [-1, -1, 0, 1, -1, 0.0, 1, 1, 0.0, -1, 1, 0.0]
|
|
341
|
+
|
|
342
|
+
this.vertexIndice = [0, 1, 2, 0, 2, 3]
|
|
343
|
+
|
|
344
|
+
this.prevViewPort = { w: 0, h: 0, canvasW: 0, canvasH: 0 }
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
WebGLRender.prototype = {
|
|
348
|
+
setViewMode(mode) {
|
|
349
|
+
this.viewMode = mode
|
|
350
|
+
},
|
|
351
|
+
enablePreserveDrawingBuffer(enable) {
|
|
352
|
+
this.preserveDrawingBuffer = enable
|
|
353
|
+
},
|
|
354
|
+
setWebGLView() {
|
|
355
|
+
const { w, h, prevViewPort } = this
|
|
356
|
+
|
|
357
|
+
if (w && h && this.canvas && this.gl) {
|
|
358
|
+
const rect = this.canvas.getBoundingClientRect()
|
|
359
|
+
const canvasH = rect.height
|
|
360
|
+
const canvasW = rect.width
|
|
361
|
+
if (!(canvasW && canvasH)) return
|
|
362
|
+
let newW
|
|
363
|
+
let newH
|
|
364
|
+
const ratioW = w / canvasW
|
|
365
|
+
const ratioH = h / canvasH
|
|
366
|
+
|
|
367
|
+
if (this.viewMode === 1) {
|
|
368
|
+
if (ratioW > ratioH) {
|
|
369
|
+
newH = canvasH
|
|
370
|
+
newW = (w * canvasH) / h
|
|
371
|
+
} else {
|
|
372
|
+
newW = canvasW
|
|
373
|
+
newH = (h * canvasW) / w
|
|
374
|
+
}
|
|
375
|
+
const dpr = window.devicePixelRatio
|
|
376
|
+
var offsetX = -(newW - canvasW) >> 1
|
|
377
|
+
var offsetY = -(newH - canvasH) >> 1
|
|
378
|
+
if (dpr !== 1) {
|
|
379
|
+
newW = newW * dpr
|
|
380
|
+
newH = newH * dpr
|
|
381
|
+
//offsetX = 0
|
|
382
|
+
//offsetY = 0
|
|
383
|
+
//修复画面裁剪比例的问题
|
|
384
|
+
offsetX = offsetX * dpr
|
|
385
|
+
offsetY = offsetY * dpr
|
|
386
|
+
}
|
|
387
|
+
Object.assign(prevViewPort, { w, h, canvasW, canvasH, offsetX, offsetY, newW, newH })
|
|
388
|
+
|
|
389
|
+
if ((offsetX, offsetY, newW, newH)) {
|
|
390
|
+
this.gl.viewport(offsetX, offsetY, newW, newH)
|
|
391
|
+
}
|
|
392
|
+
} else {
|
|
393
|
+
const dpr = window.devicePixelRatio
|
|
394
|
+
var realCanvasH = canvasH
|
|
395
|
+
var realCanvasW = canvasW
|
|
396
|
+
if (dpr !== 1) {
|
|
397
|
+
realCanvasW = realCanvasW * dpr
|
|
398
|
+
realCanvasH = realCanvasH * dpr
|
|
399
|
+
}
|
|
400
|
+
Object.assign(prevViewPort, {
|
|
401
|
+
w,
|
|
402
|
+
h,
|
|
403
|
+
realCanvasW,
|
|
404
|
+
realCanvasH,
|
|
405
|
+
offsetX: 0,
|
|
406
|
+
offsetY: 0,
|
|
407
|
+
newW: realCanvasW,
|
|
408
|
+
newH: realCanvasH,
|
|
409
|
+
})
|
|
410
|
+
if ((realCanvasW, realCanvasH)) {
|
|
411
|
+
this.gl.viewport(0, 0, realCanvasW, realCanvasH)
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
|
|
417
|
+
initGLfromCanvas(canvas) {
|
|
418
|
+
if (canvas) {
|
|
419
|
+
this.canvas = canvas
|
|
420
|
+
|
|
421
|
+
let ret = false
|
|
422
|
+
let use2dRender = false
|
|
423
|
+
|
|
424
|
+
do {
|
|
425
|
+
ret = this.initGL(canvas)
|
|
426
|
+
if (!ret) {
|
|
427
|
+
/*console.log('initGL failed');*/ break
|
|
428
|
+
}
|
|
429
|
+
ret = this.initShaders()
|
|
430
|
+
if (!ret) {
|
|
431
|
+
/*console.log('initShaders failed');*/ break
|
|
432
|
+
}
|
|
433
|
+
ret = this.initUniforms()
|
|
434
|
+
if (!ret) {
|
|
435
|
+
/*console.log('initUniforms failed');*/ break
|
|
436
|
+
}
|
|
437
|
+
} while (false)
|
|
438
|
+
|
|
439
|
+
//Webgl is not available, to switch canvas rendering
|
|
440
|
+
if (!this.gl) {
|
|
441
|
+
do {
|
|
442
|
+
this.render2d = new Canvas2dRender()
|
|
443
|
+
if (this.render2d) {
|
|
444
|
+
ret = this.render2d.bindCanvas(canvas)
|
|
445
|
+
if (!ret) {
|
|
446
|
+
console.log('init2d failed')
|
|
447
|
+
break
|
|
448
|
+
}
|
|
449
|
+
use2dRender = true
|
|
450
|
+
}
|
|
451
|
+
} while (false)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (ret && !use2dRender) {
|
|
455
|
+
this.initTextureAttr()
|
|
456
|
+
this.initTexture()
|
|
457
|
+
}
|
|
458
|
+
this.haveInit = ret
|
|
459
|
+
return ret
|
|
460
|
+
}
|
|
461
|
+
return false
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
initBkColor(bkColor) {
|
|
465
|
+
// this.bkAlpha = this.bkColor >> 24 & 0xff / 255.0
|
|
466
|
+
this.bkAlpha = 1
|
|
467
|
+
this.bkColor = bkColor
|
|
468
|
+
this.bkRed = ((this.bkColor >> 16) & 0xff) / 255.0
|
|
469
|
+
this.bkGreen = ((this.bkColor >> 8) & 0xff) / 255.0
|
|
470
|
+
this.bkBlue = (this.bkColor & 0xff) / 255.0
|
|
471
|
+
this.setbkColor = true
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
initGL(canvas) {
|
|
475
|
+
try {
|
|
476
|
+
this.gl =
|
|
477
|
+
canvas.getContext('webgl', { preserveDrawingBuffer: this.preserveDrawingBuffer }) ||
|
|
478
|
+
canvas.getContext('experimental-webgl', {
|
|
479
|
+
preserveDrawingBuffer: this.preserveDrawingBuffer,
|
|
480
|
+
}) ||
|
|
481
|
+
canvas.getContext('webgl2', { preserveDrawingBuffer: this.preserveDrawingBuffer })
|
|
482
|
+
} catch (e) {
|
|
483
|
+
//console.log('gl init failed', e)
|
|
484
|
+
return false
|
|
485
|
+
}
|
|
486
|
+
if (this.gl) {
|
|
487
|
+
return true
|
|
488
|
+
} else {
|
|
489
|
+
return false
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
initShaders() {
|
|
493
|
+
const VSHADER_SOURCE =
|
|
494
|
+
'attribute vec3 aPos; ' +
|
|
495
|
+
'attribute vec2 aVertexTextureCoord; ' +
|
|
496
|
+
'varying highp vec2 vTextureCoord; ' +
|
|
497
|
+
'void main(void){ ' +
|
|
498
|
+
' gl_Position = vec4(aPos, 1); ' +
|
|
499
|
+
' vTextureCoord = aVertexTextureCoord;' +
|
|
500
|
+
'}'
|
|
501
|
+
|
|
502
|
+
const FSHADER_SOURCE =
|
|
503
|
+
'varying highp vec2 vTextureCoord; ' +
|
|
504
|
+
'uniform sampler2D uSampler; ' +
|
|
505
|
+
'void main(void) { ' +
|
|
506
|
+
' gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); ' +
|
|
507
|
+
'}'
|
|
508
|
+
|
|
509
|
+
// compile shaders
|
|
510
|
+
const vertexShader = this.makeShader(VSHADER_SOURCE, this.gl.VERTEX_SHADER)
|
|
511
|
+
const fragmentShader = this.makeShader(FSHADER_SOURCE, this.gl.FRAGMENT_SHADER)
|
|
512
|
+
this.vShader = vertexShader
|
|
513
|
+
this.fShader = fragmentShader
|
|
514
|
+
if (!vertexShader || !fragmentShader) {
|
|
515
|
+
return false
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// create program
|
|
519
|
+
this.glProgram = this.gl.createProgram()
|
|
520
|
+
|
|
521
|
+
// attach and link shaders to the program
|
|
522
|
+
this.gl.attachShader(this.glProgram, vertexShader)
|
|
523
|
+
this.gl.attachShader(this.glProgram, fragmentShader)
|
|
524
|
+
this.gl.linkProgram(this.glProgram)
|
|
525
|
+
|
|
526
|
+
if (!this.gl.getProgramParameter(this.glProgram, this.gl.LINK_STATUS)) {
|
|
527
|
+
console.log('Unable to initialize the shader program.')
|
|
528
|
+
return false
|
|
529
|
+
} else {
|
|
530
|
+
// use program
|
|
531
|
+
this.gl.useProgram(this.glProgram)
|
|
532
|
+
return true
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
makeShader(src, type) {
|
|
536
|
+
//compile the vertex shader
|
|
537
|
+
const shader = this.gl.createShader(type)
|
|
538
|
+
this.gl.shaderSource(shader, src)
|
|
539
|
+
this.gl.compileShader(shader)
|
|
540
|
+
|
|
541
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
542
|
+
console.log(`Error compiling shader: ${this.gl.getShaderInfoLog(shader)}`)
|
|
543
|
+
return null
|
|
544
|
+
}
|
|
545
|
+
return shader
|
|
546
|
+
},
|
|
547
|
+
|
|
548
|
+
initUniforms() {
|
|
549
|
+
this.samplerUniform = this.gl.getUniformLocation(this.glProgram, 'uSampler')
|
|
550
|
+
//console.log("this.samplerUniform = ", this.samplerUniform)
|
|
551
|
+
return true
|
|
552
|
+
},
|
|
553
|
+
initTexture() {
|
|
554
|
+
this.texture = this.gl.createTexture()
|
|
555
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture)
|
|
556
|
+
//this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
557
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR)
|
|
558
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR)
|
|
559
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE)
|
|
560
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE)
|
|
561
|
+
},
|
|
562
|
+
|
|
563
|
+
initTextureAttr() {
|
|
564
|
+
// vertex data
|
|
565
|
+
const vertexBuffer = this.gl.createBuffer()
|
|
566
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer)
|
|
567
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.vertex), this.gl.STATIC_DRAW)
|
|
568
|
+
|
|
569
|
+
// indice data
|
|
570
|
+
const vertexIndiceBuffer = this.gl.createBuffer()
|
|
571
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, vertexIndiceBuffer)
|
|
572
|
+
this.gl.bufferData(
|
|
573
|
+
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
574
|
+
new Uint16Array(this.vertexIndice),
|
|
575
|
+
this.gl.STATIC_DRAW
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
// set position attribute
|
|
579
|
+
const aVertexPosition = this.gl.getAttribLocation(this.glProgram, 'aPos')
|
|
580
|
+
this.gl.vertexAttribPointer(aVertexPosition, 3, this.gl.FLOAT, false, 0, 0)
|
|
581
|
+
this.gl.enableVertexAttribArray(aVertexPosition)
|
|
582
|
+
},
|
|
583
|
+
|
|
584
|
+
uninit2d() {
|
|
585
|
+
if (this.render2d) {
|
|
586
|
+
this.render2d.unbindCanvas()
|
|
587
|
+
this.render2d = null
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
setFlipMode(flipMode) {
|
|
592
|
+
if (this.flipMode === flipMode) {
|
|
593
|
+
return
|
|
594
|
+
}
|
|
595
|
+
this.flipMode = flipMode
|
|
596
|
+
|
|
597
|
+
// default flip-None
|
|
598
|
+
let triangleTexCoords = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
|
|
599
|
+
// flip-X
|
|
600
|
+
if (flipMode === 1) {
|
|
601
|
+
triangleTexCoords = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// texture coordinate data
|
|
605
|
+
const trianglesTexCoordBuffer = this.gl.createBuffer()
|
|
606
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, trianglesTexCoordBuffer)
|
|
607
|
+
this.gl.bufferData(
|
|
608
|
+
this.gl.ARRAY_BUFFER,
|
|
609
|
+
new Float32Array(triangleTexCoords),
|
|
610
|
+
this.gl.STATIC_DRAW
|
|
611
|
+
)
|
|
612
|
+
const vertexTexCoordAttribute = this.gl.getAttribLocation(this.glProgram, 'aVertexTextureCoord')
|
|
613
|
+
this.gl.enableVertexAttribArray(vertexTexCoordAttribute)
|
|
614
|
+
this.gl.vertexAttribPointer(vertexTexCoordAttribute, 2, this.gl.FLOAT, false, 0, 0)
|
|
615
|
+
},
|
|
616
|
+
|
|
617
|
+
updateImgData(buf, w, h) {
|
|
618
|
+
this.w = w
|
|
619
|
+
this.h = h
|
|
620
|
+
this.gl.texImage2D(
|
|
621
|
+
this.gl.TEXTURE_2D,
|
|
622
|
+
0,
|
|
623
|
+
this.gl.RGBA,
|
|
624
|
+
w,
|
|
625
|
+
h,
|
|
626
|
+
0,
|
|
627
|
+
this.gl.RGBA,
|
|
628
|
+
this.gl.UNSIGNED_BYTE,
|
|
629
|
+
buf
|
|
630
|
+
)
|
|
631
|
+
// 处理某些win 机器上当窗口最小化时导致内存泄漏的问题(最小化窗口时GPU指令未执行导致,flush可强制执行)#1101120
|
|
632
|
+
this.gl.flush()
|
|
633
|
+
},
|
|
634
|
+
resize(canvas) {
|
|
635
|
+
const dpr = window.devicePixelRatio
|
|
636
|
+
|
|
637
|
+
const { width, height } = canvas.getBoundingClientRect()
|
|
638
|
+
|
|
639
|
+
const displayWidth = Math.round(width * dpr)
|
|
640
|
+
const displayHeight = Math.round(height * dpr)
|
|
641
|
+
|
|
642
|
+
// Check if the canvas is not the same size.
|
|
643
|
+
const needResize = canvas.width != displayWidth || canvas.height != displayHeight
|
|
644
|
+
|
|
645
|
+
if (needResize) {
|
|
646
|
+
// Make the canvas the same size
|
|
647
|
+
canvas.width = displayWidth
|
|
648
|
+
canvas.height = displayHeight
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
|
|
652
|
+
drawVideoFrame(videoFrame) {
|
|
653
|
+
//webgl render
|
|
654
|
+
let width = videoFrame['videoFrameParam']['width']
|
|
655
|
+
let height = videoFrame['videoFrameParam']['height']
|
|
656
|
+
if (this.gl) {
|
|
657
|
+
this.setFlipMode(videoFrame['videoFrameParam']['flipMode'])
|
|
658
|
+
this.draw(videoFrame['videoFrameBuffer'], width, height)
|
|
659
|
+
}
|
|
660
|
+
//canvas render
|
|
661
|
+
else {
|
|
662
|
+
if (this.render2d) {
|
|
663
|
+
this.render2d.setFlipMode(videoFrame['videoFrameParam']['flipMode'])
|
|
664
|
+
this.render2d.setViewMode(this.viewMode)
|
|
665
|
+
var databuffer = videoFrame['videoFrameBuffer']
|
|
666
|
+
this.render2d.drawFrame({ databuffer, width, height })
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
|
|
671
|
+
draw(rgbaBuf, w, h) {
|
|
672
|
+
this.w = w
|
|
673
|
+
this.h = h
|
|
674
|
+
if (!this.haveInit) {
|
|
675
|
+
//console.log('not init gl. can not draw')
|
|
676
|
+
return
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
//console.log("window.devicePixelRatio",window.devicePixelRatio);
|
|
680
|
+
// 视网膜屏幕分辨率矫正
|
|
681
|
+
this.resize(this.canvas)
|
|
682
|
+
|
|
683
|
+
const canvas_w = this.canvas.width
|
|
684
|
+
const canvas_h = this.canvas.height
|
|
685
|
+
|
|
686
|
+
let new_w = 0,
|
|
687
|
+
new_h = 0
|
|
688
|
+
|
|
689
|
+
if (this.viewMode !== 0) {
|
|
690
|
+
this.setWebGLView()
|
|
691
|
+
} else {
|
|
692
|
+
if (w < canvas_w && h < canvas_h) {
|
|
693
|
+
const scale_w = ((canvas_w - w) / canvas_w) * 1.0
|
|
694
|
+
const scale_h = ((canvas_h - h) / canvas_h) * 1.0
|
|
695
|
+
if (scale_w < scale_h) {
|
|
696
|
+
new_w = canvas_w
|
|
697
|
+
new_h = ((canvas_w - w) / w) * 1.0 * h + h
|
|
698
|
+
const view_port_x = 0
|
|
699
|
+
const view_port_y = (canvas_h - new_h) >> 1
|
|
700
|
+
this.gl.viewport(view_port_x, view_port_y, new_w, new_h)
|
|
701
|
+
} else {
|
|
702
|
+
new_h = canvas_h
|
|
703
|
+
new_w = ((canvas_h - h) / h) * 1.0 * w + w
|
|
704
|
+
const view_port_x = (canvas_w >> 1) - (new_w >> 1)
|
|
705
|
+
const view_port_y = 0
|
|
706
|
+
this.gl.viewport(view_port_x, view_port_y, new_w, new_h)
|
|
707
|
+
}
|
|
708
|
+
} else {
|
|
709
|
+
const scale_w = ((w - canvas_w) / w) * 1.0
|
|
710
|
+
const scale_h = ((h - canvas_h) / h) * 1.0
|
|
711
|
+
if (scale_w < scale_h) {
|
|
712
|
+
new_h = canvas_h
|
|
713
|
+
new_w = w - ((h - canvas_h) / h) * 1.0 * w
|
|
714
|
+
const view_port_x = (canvas_w >> 1) - (new_w >> 1)
|
|
715
|
+
const view_port_y = 0
|
|
716
|
+
this.gl.viewport(view_port_x, view_port_y, new_w, new_h)
|
|
717
|
+
} else {
|
|
718
|
+
new_w = canvas_w
|
|
719
|
+
new_h = h - ((w - canvas_w) / w) * 1.0 * h
|
|
720
|
+
const view_port_x = 0
|
|
721
|
+
const view_port_y = (canvas_h >> 1) - (new_h >> 1)
|
|
722
|
+
this.gl.viewport(view_port_x, view_port_y, new_w, new_h)
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (this.setbkColor) {
|
|
728
|
+
this.gl.clearColor(this.bkRed, this.bkGreen, this.bkBlue, this.bkAlpha)
|
|
729
|
+
this.gl.clear(this.gl.COLOR_BUFFER_BIT)
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
this.updateImgData(rgbaBuf, w, h)
|
|
733
|
+
|
|
734
|
+
this.gl.drawElements(this.gl.TRIANGLES, 6, this.gl.UNSIGNED_SHORT, 0)
|
|
735
|
+
},
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
module.exports = exports = WebGLRender
|