agora-electron-sdk 4.5.1 → 4.5.2-dev.2

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 (99) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/js/Decoder/gpu-utils.js +74 -0
  3. package/js/Decoder/index.js +172 -0
  4. package/js/Private/AgoraBase.js +15 -3
  5. package/js/Private/extension/AgoraBaseExtension.js +1 -0
  6. package/js/Private/internal/IrisApiEngine.js +20 -7
  7. package/js/Private/internal/RtcEngineExInternal.js +31 -16
  8. package/js/Private/ipc/main.js +21 -0
  9. package/js/Private/ipc/renderer.js +21 -0
  10. package/js/Renderer/CapabilityManager.js +99 -0
  11. package/js/Renderer/IRenderer.js +40 -11
  12. package/js/Renderer/IRendererCache.js +75 -0
  13. package/js/Renderer/RendererCache.js +26 -63
  14. package/js/Renderer/RendererManager.js +259 -38
  15. package/js/Renderer/WebCodecsRenderer/index.js +109 -0
  16. package/js/Renderer/WebCodecsRendererCache.js +115 -0
  17. package/js/Renderer/WebGLRenderer/index.js +115 -67
  18. package/js/Renderer/YUVCanvasRenderer/index.js +5 -3
  19. package/js/Renderer/index.js +0 -1
  20. package/js/Types.js +51 -1
  21. package/js/Utils.js +47 -7
  22. package/package.json +28 -11
  23. package/scripts/checkElectron.js +4 -2
  24. package/scripts/download.js +102 -0
  25. package/scripts/downloadPrebuild.js +2 -1
  26. package/scripts/synclib.js +2 -2
  27. package/ts/Decoder/gpu-utils.ts +92 -0
  28. package/ts/Decoder/index.ts +206 -0
  29. package/ts/Private/AgoraBase.ts +18 -4
  30. package/ts/Private/IAgoraRtcEngine.ts +6 -7
  31. package/ts/Private/IAgoraRtcEngineEx.ts +2 -1
  32. package/ts/Private/extension/AgoraBaseExtension.ts +14 -1
  33. package/ts/Private/internal/IrisApiEngine.ts +21 -7
  34. package/ts/Private/internal/RtcEngineExInternal.ts +27 -8
  35. package/ts/Private/ipc/main.ts +22 -0
  36. package/ts/Private/ipc/renderer.ts +21 -0
  37. package/ts/Renderer/CapabilityManager.ts +126 -0
  38. package/ts/Renderer/IRenderer.ts +52 -17
  39. package/ts/Renderer/IRendererCache.ts +96 -0
  40. package/ts/Renderer/RendererCache.ts +42 -85
  41. package/ts/Renderer/RendererManager.ts +342 -52
  42. package/ts/Renderer/WebCodecsRenderer/index.ts +145 -0
  43. package/ts/Renderer/WebCodecsRendererCache.ts +137 -0
  44. package/ts/Renderer/WebGLRenderer/index.ts +153 -107
  45. package/ts/Renderer/YUVCanvasRenderer/index.ts +24 -22
  46. package/ts/Renderer/index.ts +0 -1
  47. package/ts/Types.ts +130 -7
  48. package/ts/Utils.ts +53 -7
  49. package/types/Decoder/gpu-utils.d.ts +21 -0
  50. package/types/Decoder/gpu-utils.d.ts.map +1 -0
  51. package/types/Decoder/index.d.ts +26 -0
  52. package/types/Decoder/index.d.ts.map +1 -0
  53. package/types/Private/AgoraBase.d.ts +18 -4
  54. package/types/Private/AgoraBase.d.ts.map +1 -1
  55. package/types/Private/IAgoraRtcEngine.d.ts +6 -7
  56. package/types/Private/IAgoraRtcEngine.d.ts.map +1 -1
  57. package/types/Private/IAgoraRtcEngineEx.d.ts +2 -1
  58. package/types/Private/IAgoraRtcEngineEx.d.ts.map +1 -1
  59. package/types/Private/extension/AgoraBaseExtension.d.ts +13 -1
  60. package/types/Private/extension/AgoraBaseExtension.d.ts.map +1 -1
  61. package/types/Private/internal/IrisApiEngine.d.ts +2 -0
  62. package/types/Private/internal/IrisApiEngine.d.ts.map +1 -1
  63. package/types/Private/internal/RtcEngineExInternal.d.ts +2 -0
  64. package/types/Private/internal/RtcEngineExInternal.d.ts.map +1 -1
  65. package/types/Private/ipc/main.d.ts +2 -0
  66. package/types/Private/ipc/main.d.ts.map +1 -0
  67. package/types/Private/ipc/renderer.d.ts +3 -0
  68. package/types/Private/ipc/renderer.d.ts.map +1 -0
  69. package/types/Renderer/CapabilityManager.d.ts +20 -0
  70. package/types/Renderer/CapabilityManager.d.ts.map +1 -0
  71. package/types/Renderer/IRenderer.d.ts +8 -7
  72. package/types/Renderer/IRenderer.d.ts.map +1 -1
  73. package/types/Renderer/IRendererCache.d.ts +26 -0
  74. package/types/Renderer/IRendererCache.d.ts.map +1 -0
  75. package/types/Renderer/RendererCache.d.ts +6 -18
  76. package/types/Renderer/RendererCache.d.ts.map +1 -1
  77. package/types/Renderer/RendererManager.d.ts +49 -15
  78. package/types/Renderer/RendererManager.d.ts.map +1 -1
  79. package/types/Renderer/WebCodecsRenderer/index.d.ts +14 -0
  80. package/types/Renderer/WebCodecsRenderer/index.d.ts.map +1 -0
  81. package/types/Renderer/WebCodecsRendererCache.d.ts +15 -0
  82. package/types/Renderer/WebCodecsRendererCache.d.ts.map +1 -0
  83. package/types/Renderer/WebGLRenderer/index.d.ts +5 -3
  84. package/types/Renderer/WebGLRenderer/index.d.ts.map +1 -1
  85. package/types/Renderer/YUVCanvasRenderer/index.d.ts +1 -1
  86. package/types/Renderer/YUVCanvasRenderer/index.d.ts.map +1 -1
  87. package/types/Renderer/index.d.ts +0 -1
  88. package/types/Renderer/index.d.ts.map +1 -1
  89. package/types/Types.d.ts +99 -8
  90. package/types/Types.d.ts.map +1 -1
  91. package/types/Utils.d.ts +4 -0
  92. package/types/Utils.d.ts.map +1 -1
  93. package/js/Renderer/IRendererManager.js +0 -229
  94. package/scripts/publishCN/common.sh +0 -19
  95. package/scripts/publishCN/rewrite-dep.sh +0 -22
  96. package/scripts/publishCN/rewrite-example.sh +0 -22
  97. package/ts/Renderer/IRendererManager.ts +0 -316
  98. package/types/Renderer/IRendererManager.d.ts +0 -56
  99. package/types/Renderer/IRendererManager.d.ts.map +0 -1
@@ -0,0 +1,137 @@
1
+ import createAgoraRtcEngine from '../AgoraSdk';
2
+ import { WebCodecsDecoder } from '../Decoder/index';
3
+ import { EncodedVideoFrameInfo, VideoStreamType } from '../Private/AgoraBase';
4
+ import { IRtcEngineEx } from '../Private/IAgoraRtcEngineEx';
5
+ import { AgoraElectronBridge } from '../Private/internal/IrisApiEngine';
6
+
7
+ import { RendererContext, RendererType } from '../Types';
8
+ import { AgoraEnv, logInfo } from '../Utils';
9
+
10
+ import { IRendererCache, isUseConnection } from './IRendererCache';
11
+ import { WebCodecsRenderer } from './WebCodecsRenderer/index';
12
+
13
+ export class WebCodecsRendererCache extends IRendererCache {
14
+ private _decoder?: WebCodecsDecoder | null;
15
+ private _engine?: IRtcEngineEx;
16
+ private _firstFrame = true;
17
+
18
+ constructor(context: RendererContext) {
19
+ super(context);
20
+ this._engine = createAgoraRtcEngine();
21
+ this._decoder = new WebCodecsDecoder(
22
+ this.renderers as WebCodecsRenderer[],
23
+ this.onDecoderError.bind(this),
24
+ context
25
+ );
26
+ this.draw();
27
+ }
28
+
29
+ onDecoderError(e: any) {
30
+ logInfo('webCodecsDecoder decode failed, fallback to native decoder', e);
31
+ AgoraEnv.AgoraRendererManager?.handleWebCodecsFallback(this.cacheContext);
32
+ }
33
+
34
+ onEncodedVideoFrameReceived(...[data, buffer]: any) {
35
+ let _data: any;
36
+ try {
37
+ _data = JSON.parse(data) ?? {};
38
+ } catch (e) {
39
+ _data = {};
40
+ }
41
+ if (
42
+ Object.keys(_data).length === 0 ||
43
+ !this._decoder ||
44
+ this.cacheContext.uid !== _data.uid
45
+ )
46
+ return;
47
+ if (this._firstFrame) {
48
+ for (let renderer of this.renderers) {
49
+ if (renderer.rendererType !== RendererType.WEBCODECSRENDERER) {
50
+ continue;
51
+ }
52
+ renderer.bind(renderer.context.view);
53
+ }
54
+
55
+ try {
56
+ this._decoder.decoderConfigure(_data.videoEncodedFrameInfo);
57
+ } catch (error: any) {
58
+ logInfo(error);
59
+ return;
60
+ }
61
+ this._firstFrame = false;
62
+ }
63
+ if (this.shouldFallback(_data.videoEncodedFrameInfo)) {
64
+ AgoraEnv.AgoraRendererManager?.handleWebCodecsFallback(this.cacheContext);
65
+ } else {
66
+ this._decoder.decodeFrame(
67
+ buffer,
68
+ _data.videoEncodedFrameInfo,
69
+ new Date().getTime()
70
+ );
71
+ }
72
+ }
73
+
74
+ public draw() {
75
+ if (isUseConnection(this.cacheContext)) {
76
+ this._engine?.setRemoteVideoSubscriptionOptionsEx(
77
+ this.cacheContext.uid!,
78
+ {
79
+ type: VideoStreamType.VideoStreamHigh,
80
+ encodedFrameOnly: true,
81
+ },
82
+ {
83
+ channelId: this.cacheContext.channelId,
84
+ localUid: this.cacheContext.localUid,
85
+ }
86
+ );
87
+ } else {
88
+ this._engine?.setRemoteVideoSubscriptionOptions(this.cacheContext.uid!, {
89
+ type: VideoStreamType.VideoStreamHigh,
90
+ encodedFrameOnly: true,
91
+ });
92
+ }
93
+ AgoraElectronBridge.OnEvent(
94
+ `call_back_with_encoded_video_frame_${this.cacheContext.uid}`,
95
+ (...params: any) => {
96
+ try {
97
+ this.onEncodedVideoFrameReceived(...params);
98
+ } catch (e) {
99
+ console.error(e);
100
+ }
101
+ }
102
+ );
103
+ }
104
+
105
+ public shouldFallback(frameInfo: EncodedVideoFrameInfo): boolean {
106
+ let shouldFallback = false;
107
+ if (!frameInfo.codecType) {
108
+ shouldFallback = true;
109
+ logInfo('codecType is not supported, fallback to native decoder');
110
+ } else {
111
+ const mapping =
112
+ AgoraEnv.CapabilityManager?.frameCodecMapping[frameInfo.codecType];
113
+ if (mapping === undefined) {
114
+ shouldFallback = true;
115
+ logInfo('codecType is not supported, fallback to native decoder');
116
+ } else if (
117
+ mapping.minWidth >= frameInfo.width! &&
118
+ mapping.minHeight >= frameInfo.height! &&
119
+ mapping.maxWidth <= frameInfo.width! &&
120
+ mapping.maxHeight <= frameInfo.height!
121
+ ) {
122
+ shouldFallback = true;
123
+ logInfo('frame size is not supported, fallback to native decoder');
124
+ }
125
+ }
126
+ return shouldFallback;
127
+ }
128
+
129
+ public release(): void {
130
+ AgoraElectronBridge.UnEvent(
131
+ `call_back_with_encoded_video_frame_${this.cacheContext.uid}`
132
+ );
133
+ this._decoder?.release();
134
+ this._decoder = null;
135
+ super.release();
136
+ }
137
+ }
@@ -1,5 +1,6 @@
1
1
  import { VideoFrame } from '../../Private/AgoraMediaBase';
2
- import { logWarn } from '../../Utils';
2
+ import { RendererType } from '../../Types';
3
+ import { AgoraEnv, logWarn } from '../../Utils';
3
4
  import { IRenderer } from '../IRenderer';
4
5
 
5
6
  export type WebGLFallback = (renderer: WebGLRenderer, error: Error) => void;
@@ -7,59 +8,72 @@ export type WebGLFallback = (renderer: WebGLRenderer, error: Error) => void;
7
8
  const createProgramFromSources =
8
9
  require('./webgl-utils').createProgramFromSources;
9
10
 
10
- const vertexShaderSource =
11
- 'attribute vec2 a_position;' +
12
- 'attribute vec2 a_texCoord;' +
13
- 'uniform vec2 u_resolution;' +
14
- 'varying vec2 v_texCoord;' +
15
- 'void main() {' +
16
- 'vec2 zeroToOne = a_position / u_resolution;' +
17
- ' vec2 zeroToTwo = zeroToOne * 2.0;' +
18
- ' vec2 clipSpace = zeroToTwo - 1.0;' +
19
- ' gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);' +
20
- 'v_texCoord = a_texCoord;' +
21
- '}';
22
- const yuvShaderSource =
23
- 'precision mediump float;' +
24
- 'uniform sampler2D Ytex;' +
25
- 'uniform sampler2D Utex;' +
26
- 'uniform sampler2D Vtex;' +
27
- 'varying vec2 v_texCoord;' +
28
- 'void main(void) {' +
29
- ' float nx,ny,r,g,b,y,u,v;' +
30
- ' mediump vec4 txl,ux,vx;' +
31
- ' nx=v_texCoord[0];' +
32
- ' ny=v_texCoord[1];' +
33
- ' y=texture2D(Ytex,vec2(nx,ny)).r;' +
34
- ' u=texture2D(Utex,vec2(nx,ny)).r;' +
35
- ' v=texture2D(Vtex,vec2(nx,ny)).r;' +
36
- ' y=1.1643*(y-0.0625);' +
37
- ' u=u-0.5;' +
38
- ' v=v-0.5;' +
39
- ' r=y+1.5958*v;' +
40
- ' g=y-0.39173*u-0.81290*v;' +
41
- ' b=y+2.017*u;' +
42
- ' gl_FragColor=vec4(r,g,b,1.0);' +
43
- '}';
11
+ const vertexShaderSource = `
12
+ attribute vec2 a_position;
13
+ attribute vec2 a_texCoord;
14
+ uniform vec2 u_resolution;
15
+ varying vec2 v_texCoord;
16
+ void main() {
17
+ vec2 zeroToOne = a_position / u_resolution;
18
+ vec2 zeroToTwo = zeroToOne * 2.0;
19
+ vec2 clipSpace = zeroToTwo - 1.0;
20
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
21
+ v_texCoord = a_texCoord;
22
+ }`;
23
+ const yuvShaderSource = `
24
+ precision mediump float;
25
+ uniform sampler2D Ytex;
26
+ uniform sampler2D Utex;
27
+ uniform sampler2D Vtex;
28
+ uniform sampler2D Atex;
29
+ uniform bool hasAlpha;
30
+ varying vec2 v_texCoord;
31
+ void main(void) {
32
+ float nx,ny,r,g,b,y,u,v,a;
33
+ mediump vec4 txl,ux,vx;
34
+ nx=v_texCoord[0];
35
+ ny=v_texCoord[1];
36
+ y=texture2D(Ytex,vec2(nx,ny)).r;
37
+ u=texture2D(Utex,vec2(nx,ny)).r;
38
+ v=texture2D(Vtex,vec2(nx,ny)).r;
39
+ if (hasAlpha) {
40
+ a=texture2D(Atex,vec2(nx,ny)).r;
41
+ } else {
42
+ a=1.0;
43
+ }
44
+ y=1.1643*(y-0.0625);
45
+ u=u-0.5;
46
+ v=v-0.5;
47
+ r=y+1.5958*v;
48
+ g=y-0.39173*u-0.81290*v;
49
+ b=y+2.017*u;
50
+ gl_FragColor=vec4(r,g,b,a);
51
+ }`;
44
52
 
45
53
  export class WebGLRenderer extends IRenderer {
46
- gl?: WebGLRenderingContext | WebGL2RenderingContext | null;
47
- program?: WebGLProgram;
54
+ gl: WebGLRenderingContext | WebGL2RenderingContext | null;
55
+ program: WebGLProgram | null;
48
56
  positionLocation?: number;
49
57
  texCoordLocation?: number;
50
58
  yTexture: WebGLTexture | null;
51
59
  uTexture: WebGLTexture | null;
52
60
  vTexture: WebGLTexture | null;
61
+ aTexture: WebGLTexture | null;
62
+ hasAlpha: WebGLUniformLocation | null;
53
63
  texCoordBuffer: WebGLBuffer | null;
54
64
  surfaceBuffer: WebGLBuffer | null;
55
65
  fallback?: WebGLFallback;
56
66
 
57
67
  constructor(fallback?: WebGLFallback) {
58
68
  super();
59
- this.gl = undefined;
69
+ this.gl = null;
70
+ this.rendererType = RendererType.WEBGL;
71
+ this.program = null;
60
72
  this.yTexture = null;
61
73
  this.uTexture = null;
62
74
  this.vTexture = null;
75
+ this.aTexture = null;
76
+ this.hasAlpha = null;
63
77
  this.texCoordBuffer = null;
64
78
  this.surfaceBuffer = null;
65
79
  this.fallback = fallback;
@@ -87,10 +101,10 @@ export class WebGLRenderer extends IRenderer {
87
101
  const context = this.canvas?.getContext(contextName, {
88
102
  depth: true,
89
103
  stencil: true,
90
- alpha: false,
104
+ alpha: true,
91
105
  antialias: false,
92
106
  premultipliedAlpha: true,
93
- preserveDrawingBuffer: true,
107
+ preserveDrawingBuffer: !AgoraEnv.encodeAlpha,
94
108
  powerPreference: 'default',
95
109
  failIfMajorPerformanceCaveat: false,
96
110
  });
@@ -112,11 +126,15 @@ export class WebGLRenderer extends IRenderer {
112
126
  }
113
127
 
114
128
  // Set clear color to black, fully opaque
115
- this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
129
+ this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
116
130
  // Enable depth testing
117
131
  this.gl.enable(this.gl.DEPTH_TEST);
118
132
  // Near things obscure far things
119
133
  this.gl.depthFunc(this.gl.LEQUAL);
134
+ // Enable blending
135
+ this.gl.enable(this.gl.BLEND);
136
+ // Set blending function
137
+ this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
120
138
  // Clear the color as well as the depth buffer.
121
139
  this.gl.clear(
122
140
  this.gl.COLOR_BUFFER_BIT |
@@ -147,7 +165,7 @@ export class WebGLRenderer extends IRenderer {
147
165
  );
148
166
 
149
167
  this.releaseTextures();
150
- this.gl = undefined;
168
+ this.gl = null;
151
169
 
152
170
  super.unbind();
153
171
  }
@@ -162,6 +180,7 @@ export class WebGLRenderer extends IRenderer {
162
180
  uBuffer,
163
181
  vBuffer,
164
182
  rotation,
183
+ alphaBuffer,
165
184
  }: VideoFrame) {
166
185
  this.rotateCanvas({ width, height, rotation });
167
186
  this.updateRenderMode();
@@ -206,57 +225,81 @@ export class WebGLRenderer extends IRenderer {
206
225
 
207
226
  this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1);
208
227
 
209
- this.gl.activeTexture(this.gl.TEXTURE0);
210
- this.gl.bindTexture(this.gl.TEXTURE_2D, this.yTexture);
211
- this.gl.texImage2D(
212
- this.gl.TEXTURE_2D,
213
- 0,
214
- this.gl.LUMINANCE,
215
- // Should use xWidth instead of width here (yStide)
216
- xWidth,
217
- height!,
218
- 0,
219
- this.gl.LUMINANCE,
220
- this.gl.UNSIGNED_BYTE,
221
- yBuffer!
222
- );
228
+ type TextureInfo = {
229
+ texture: WebGLTexture | null;
230
+ stride: number;
231
+ height: number;
232
+ pixels: ArrayBufferView | null;
233
+ };
223
234
 
224
- this.gl.activeTexture(this.gl.TEXTURE1);
225
- this.gl.bindTexture(this.gl.TEXTURE_2D, this.uTexture);
226
- this.gl.texImage2D(
227
- this.gl.TEXTURE_2D,
228
- 0,
229
- this.gl.LUMINANCE,
230
- uStride!,
231
- height! / 2,
232
- 0,
233
- this.gl.LUMINANCE,
234
- this.gl.UNSIGNED_BYTE,
235
- uBuffer!
236
- );
235
+ const activeTexture = (
236
+ textureIndex: number,
237
+ { texture, stride, height, pixels }: TextureInfo
238
+ ) => {
239
+ if (!this.gl) return;
237
240
 
238
- this.gl.activeTexture(this.gl.TEXTURE2);
239
- this.gl.bindTexture(this.gl.TEXTURE_2D, this.vTexture);
240
- this.gl.texImage2D(
241
- this.gl.TEXTURE_2D,
242
- 0,
243
- this.gl.LUMINANCE,
244
- vStride!,
245
- height! / 2,
246
- 0,
247
- this.gl.LUMINANCE,
248
- this.gl.UNSIGNED_BYTE,
249
- vBuffer!
250
- );
241
+ this.gl.activeTexture(textureIndex);
242
+ this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
243
+ this.gl.texImage2D(
244
+ this.gl.TEXTURE_2D,
245
+ 0,
246
+ this.gl.LUMINANCE,
247
+ stride,
248
+ height,
249
+ 0,
250
+ this.gl.LUMINANCE,
251
+ this.gl.UNSIGNED_BYTE,
252
+ pixels
253
+ );
254
+ };
255
+
256
+ const textures: Record<number, TextureInfo> = {
257
+ [this.gl.TEXTURE0]: {
258
+ texture: this.yTexture,
259
+ stride: yStride!,
260
+ height: height!,
261
+ pixels: yBuffer!,
262
+ },
263
+ [this.gl.TEXTURE1]: {
264
+ texture: this.uTexture,
265
+ stride: uStride!,
266
+ height: height! / 2,
267
+ pixels: uBuffer!,
268
+ },
269
+ [this.gl.TEXTURE2]: {
270
+ texture: this.vTexture,
271
+ stride: vStride!,
272
+ height: height! / 2,
273
+ pixels: vBuffer!,
274
+ },
275
+ };
276
+ if (alphaBuffer) {
277
+ textures[this.gl.TEXTURE3] = {
278
+ texture: this.aTexture,
279
+ stride: width!,
280
+ height: height!,
281
+ pixels: alphaBuffer,
282
+ };
283
+ this.gl.uniform1i(this.hasAlpha, 1);
284
+ } else {
285
+ this.gl.uniform1i(this.hasAlpha, 0);
286
+ }
287
+
288
+ for (const textureIndex in textures) {
289
+ if (textures.hasOwnProperty(textureIndex)) {
290
+ activeTexture(+textureIndex, textures[textureIndex]!);
291
+ }
292
+ }
251
293
 
252
294
  this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
295
+
253
296
  super.drawFrame();
254
297
  }
255
298
 
256
299
  protected override rotateCanvas({ width, height, rotation }: VideoFrame) {
257
300
  super.rotateCanvas({ width, height, rotation });
258
301
 
259
- if (!this.gl) return;
302
+ if (!this.gl || !this.program) return;
260
303
 
261
304
  this.gl.viewport(0, 0, width!, height!);
262
305
 
@@ -328,34 +371,40 @@ export class WebGLRenderer extends IRenderer {
328
371
  );
329
372
 
330
373
  const resolutionLocation = this.gl.getUniformLocation(
331
- this.program!,
374
+ this.program,
332
375
  'u_resolution'
333
376
  );
334
377
  this.gl.uniform2f(resolutionLocation, width!, height!);
335
378
  }
336
379
 
337
380
  private initTextures() {
338
- if (!this.gl) return;
381
+ if (!this.gl || !this.program) return;
339
382
 
340
383
  this.positionLocation = this.gl.getAttribLocation(
341
- this.program!,
384
+ this.program,
342
385
  'a_position'
343
386
  );
344
387
  this.texCoordLocation = this.gl.getAttribLocation(
345
- this.program!,
388
+ this.program,
346
389
  'a_texCoord'
347
390
  );
348
391
 
392
+ this.hasAlpha = this.gl.getUniformLocation(this.program, 'hasAlpha');
393
+
349
394
  this.surfaceBuffer = this.gl.createBuffer();
350
395
  this.texCoordBuffer = this.gl.createBuffer();
351
396
 
352
- const createTexture = (textureIndex: number) => {
353
- if (!this.gl) return null;
397
+ const createTexture = (
398
+ texture: number,
399
+ textureIndex: number,
400
+ textureName: string
401
+ ) => {
402
+ if (!this.gl || !this.program) return null;
354
403
 
355
404
  // Create a texture.
356
- this.gl.activeTexture(textureIndex);
357
- const texture = this.gl.createTexture();
358
- this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
405
+ this.gl.activeTexture(texture);
406
+ const textureObj = this.gl.createTexture();
407
+ this.gl.bindTexture(this.gl.TEXTURE_2D, textureObj);
359
408
  // Set the parameters so we can render any size
360
409
  this.gl.texParameteri(
361
410
  this.gl.TEXTURE_2D,
@@ -377,26 +426,23 @@ export class WebGLRenderer extends IRenderer {
377
426
  this.gl.TEXTURE_MAG_FILTER,
378
427
  this.gl.NEAREST
379
428
  );
380
- return texture;
381
- };
382
-
383
- this.yTexture = createTexture(this.gl.TEXTURE0);
384
- this.uTexture = createTexture(this.gl.TEXTURE1);
385
- this.vTexture = createTexture(this.gl.TEXTURE2);
386
429
 
387
- const y = this.gl.getUniformLocation(this.program!, 'Ytex');
388
- this.gl.uniform1i(y, 0); /* Bind Ytex to texture unit 0 */
389
-
390
- const u = this.gl.getUniformLocation(this.program!, 'Utex');
391
- this.gl.uniform1i(u, 1); /* Bind Utex to texture unit 1 */
430
+ this.gl.uniform1i(
431
+ this.gl.getUniformLocation(this.program, textureName),
432
+ textureIndex
433
+ ); /* Bind Ytex to texture unit index */
434
+ return textureObj;
435
+ };
392
436
 
393
- const v = this.gl.getUniformLocation(this.program!, 'Vtex');
394
- this.gl.uniform1i(v, 2); /* Bind Vtex to texture unit 2 */
437
+ this.yTexture = createTexture(this.gl.TEXTURE0, 0, 'Ytex');
438
+ this.uTexture = createTexture(this.gl.TEXTURE1, 1, 'Utex');
439
+ this.vTexture = createTexture(this.gl.TEXTURE2, 2, 'Vtex');
440
+ this.aTexture = createTexture(this.gl.TEXTURE3, 3, 'Atex');
395
441
  }
396
442
 
397
443
  private releaseTextures() {
398
- this.gl?.deleteProgram(this.program!);
399
- this.program = undefined;
444
+ this.gl?.deleteProgram(this.program);
445
+ this.program = null;
400
446
 
401
447
  this.positionLocation = undefined;
402
448
  this.texCoordLocation = undefined;
@@ -24,35 +24,37 @@ export class YUVCanvasRenderer extends IRenderer {
24
24
  uBuffer,
25
25
  vBuffer,
26
26
  rotation,
27
+ alphaBuffer,
27
28
  }: VideoFrame) {
28
29
  this.rotateCanvas({ width, height, rotation });
29
30
  this.updateRenderMode();
30
31
 
31
32
  if (!this.frameSink) return;
32
33
 
33
- this.frameSink.drawFrame(
34
- YUVBuffer.frame(
35
- YUVBuffer.format({
36
- width,
37
- height,
38
- chromaWidth: width! / 2,
39
- chromaHeight: height! / 2,
40
- cropLeft: yStride! - width!,
41
- }),
42
- {
43
- bytes: yBuffer,
44
- stride: yStride,
45
- },
46
- {
47
- bytes: uBuffer,
48
- stride: uStride,
49
- },
50
- {
51
- bytes: vBuffer,
52
- stride: vStride,
53
- }
54
- )
34
+ const frame = YUVBuffer.frame(
35
+ YUVBuffer.format({
36
+ width,
37
+ height,
38
+ chromaWidth: width! / 2,
39
+ chromaHeight: height! / 2,
40
+ cropLeft: yStride! - width!,
41
+ }),
42
+ {
43
+ bytes: yBuffer,
44
+ stride: yStride,
45
+ },
46
+ {
47
+ bytes: uBuffer,
48
+ stride: uStride,
49
+ },
50
+ {
51
+ bytes: vBuffer,
52
+ stride: vStride,
53
+ }
55
54
  );
55
+ frame.a = alphaBuffer;
56
+ this.frameSink.drawFrame(frame);
57
+
56
58
  super.drawFrame();
57
59
  }
58
60
 
@@ -1,2 +1 @@
1
1
  export * from './IRenderer';
2
- export * from './IRendererManager';