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
@@ -1,80 +1,301 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.RendererManager = void 0;
7
+ const AgoraSdk_1 = __importDefault(require("../AgoraSdk"));
8
+ const AgoraBase_1 = require("../Private/AgoraBase");
9
+ const AgoraMediaBase_1 = require("../Private/AgoraMediaBase");
4
10
  const Types_1 = require("../Types");
5
11
  const Utils_1 = require("../Utils");
6
- const IRendererManager_1 = require("./IRendererManager");
12
+ const IRendererCache_1 = require("./IRendererCache");
13
+ const RendererCache_1 = require("./RendererCache");
14
+ const WebCodecsRenderer_1 = require("./WebCodecsRenderer");
15
+ const WebCodecsRendererCache_1 = require("./WebCodecsRendererCache");
7
16
  const WebGLRenderer_1 = require("./WebGLRenderer");
8
17
  const YUVCanvasRenderer_1 = require("./YUVCanvasRenderer");
9
18
  /**
10
19
  * @ignore
11
20
  */
12
- class RendererManager extends IRendererManager_1.IRendererManager {
13
- set rendererType(rendererType) {
14
- if (this._rendererType !== rendererType) {
15
- this._rendererType = rendererType;
16
- }
17
- }
18
- get rendererType() {
19
- return this._rendererType;
20
- }
21
+ class RendererManager {
21
22
  constructor() {
22
- super();
23
- this._rendererType = (0, Utils_1.isSupportWebGL)()
23
+ /**
24
+ * Currently, the remote video frame is observed in the pre-renderer position and you can not change it.
25
+ * the local video frame is observed in the pre-encoder position by default, and you can change it.
26
+ * @ignore
27
+ */
28
+ this.defaultObservedFramePosition = AgoraMediaBase_1.VideoModulePosition.PositionPreRenderer |
29
+ AgoraMediaBase_1.VideoModulePosition.PositionPreEncoder;
30
+ this.renderingFps = 15;
31
+ this._currentFrameCount = 0;
32
+ this._previousFirstFrameTime = 0;
33
+ this._rendererCaches = [];
34
+ this._context = {
35
+ renderMode: AgoraMediaBase_1.RenderModeType.RenderModeHidden,
36
+ mirrorMode: AgoraBase_1.VideoMirrorModeType.VideoMirrorModeDisabled,
37
+ };
38
+ this.rendererType = (0, Utils_1.isSupportWebGL)()
24
39
  ? Types_1.RendererType.WEBGL
25
40
  : Types_1.RendererType.SOFTWARE;
26
41
  }
27
- /**
28
- * @deprecated Use rendererType instead
29
- */
30
- setRenderMode(mode) {
31
- this.rendererType = mode;
32
- }
33
- /**
34
- * @deprecated Use renderingFps instead
35
- */
36
- setFPS(fps) {
42
+ setRenderingFps(fps) {
37
43
  this.renderingFps = fps;
44
+ if (this._renderingTimer) {
45
+ this.stopRendering();
46
+ this.startRendering();
47
+ }
48
+ }
49
+ set defaultChannelId(channelId) {
50
+ this._context.channelId = channelId;
51
+ }
52
+ get defaultChannelId() {
53
+ return this._context.channelId ?? '';
54
+ }
55
+ get defaultRenderMode() {
56
+ return this._context.renderMode;
57
+ }
58
+ get defaultMirrorMode() {
59
+ return this._context.mirrorMode;
60
+ }
61
+ release() {
62
+ this.stopRendering();
63
+ this.clearRendererCache();
38
64
  }
39
- /**
40
- * @deprecated Use getRendererCache instead
41
- */
42
- getRender(context) {
43
- return this.getRendererCache(context);
65
+ presetRendererContext(context) {
66
+ //this is for preset default value
67
+ context.renderMode = context.renderMode || this.defaultRenderMode;
68
+ context.mirrorMode = context.mirrorMode || this.defaultMirrorMode;
69
+ context.useWebCodecsDecoder = context.useWebCodecsDecoder || false;
70
+ context.enableFps = context.enableFps || false;
71
+ context.position = context.position || this.defaultObservedFramePosition;
72
+ if (!Utils_1.AgoraEnv.CapabilityManager?.webCodecsDecoderEnabled) {
73
+ context.useWebCodecsDecoder = false;
74
+ }
75
+ switch (context.sourceType) {
76
+ case AgoraMediaBase_1.VideoSourceType.VideoSourceRemote:
77
+ if (context.uid === undefined) {
78
+ throw new Error('uid is required');
79
+ }
80
+ context.channelId = context.channelId ?? this.defaultChannelId;
81
+ break;
82
+ case AgoraMediaBase_1.VideoSourceType.VideoSourceMediaPlayer:
83
+ if (context.mediaPlayerId === undefined) {
84
+ throw new Error('mediaPlayerId is required');
85
+ }
86
+ context.channelId = '';
87
+ context.uid = context.mediaPlayerId;
88
+ break;
89
+ case undefined:
90
+ if (context.uid) {
91
+ context.sourceType = AgoraMediaBase_1.VideoSourceType.VideoSourceRemote;
92
+ }
93
+ break;
94
+ default:
95
+ context.channelId = '';
96
+ context.uid = 0;
97
+ break;
98
+ }
99
+ return context;
100
+ }
101
+ addOrRemoveRenderer(context) {
102
+ // To be compatible with the old API
103
+ let { setupMode = AgoraBase_1.VideoViewSetupMode.VideoViewSetupAdd } = context;
104
+ if (!context.view)
105
+ setupMode = AgoraBase_1.VideoViewSetupMode.VideoViewSetupRemove;
106
+ switch (setupMode) {
107
+ case AgoraBase_1.VideoViewSetupMode.VideoViewSetupAdd:
108
+ return this.addRendererToCache(context);
109
+ case AgoraBase_1.VideoViewSetupMode.VideoViewSetupRemove:
110
+ this.removeRendererFromCache(context);
111
+ return undefined;
112
+ case AgoraBase_1.VideoViewSetupMode.VideoViewSetupReplace:
113
+ this.removeRendererFromCache(context);
114
+ return this.addRendererToCache(context);
115
+ }
44
116
  }
45
- createRenderer(context, rendererType) {
46
- if (rendererType === undefined) {
47
- rendererType = this.rendererType;
117
+ addRendererToCache(context) {
118
+ const checkedContext = this.presetRendererContext(context);
119
+ if (!checkedContext.view)
120
+ return undefined;
121
+ if (this.findRenderer(checkedContext.view)) {
122
+ throw new Error('You have already added this view to the renderer');
123
+ }
124
+ let rendererCache = this.getRendererCache(checkedContext);
125
+ if (!rendererCache) {
126
+ if (context.useWebCodecsDecoder) {
127
+ rendererCache = new WebCodecsRendererCache_1.WebCodecsRendererCache(checkedContext);
128
+ }
129
+ else {
130
+ rendererCache = new RendererCache_1.RendererCache(checkedContext);
131
+ }
132
+ this._rendererCaches.push(rendererCache);
133
+ }
134
+ rendererCache.addRenderer(this.createRenderer(checkedContext));
135
+ if (!context.useWebCodecsDecoder) {
136
+ this.startRendering();
48
137
  }
138
+ return rendererCache;
139
+ }
140
+ removeRendererFromCache(context) {
141
+ const checkedContext = this.presetRendererContext(context);
142
+ const rendererCache = this.getRendererCache(checkedContext);
143
+ if (!rendererCache)
144
+ return;
145
+ if (checkedContext.view) {
146
+ const renderer = rendererCache.findRenderer(checkedContext.view);
147
+ if (!renderer)
148
+ return;
149
+ rendererCache.removeRenderer(renderer);
150
+ }
151
+ else {
152
+ rendererCache.removeRenderer();
153
+ }
154
+ if (rendererCache.renderers.length === 0) {
155
+ rendererCache.release();
156
+ this._rendererCaches.splice(this._rendererCaches.indexOf(rendererCache), 1);
157
+ }
158
+ }
159
+ clearRendererCache() {
160
+ for (const rendererCache of this._rendererCaches) {
161
+ rendererCache.release();
162
+ }
163
+ this._rendererCaches.splice(0);
164
+ }
165
+ getRendererCache(context) {
166
+ return this._rendererCaches.find((cache) => cache.key === (0, IRendererCache_1.generateRendererCacheKey)(context));
167
+ }
168
+ getRenderers(context) {
169
+ return this.getRendererCache(context)?.renderers || [];
170
+ }
171
+ findRenderer(view) {
172
+ for (const rendererCache of this._rendererCaches) {
173
+ const renderer = rendererCache.findRenderer(view);
174
+ if (renderer)
175
+ return renderer;
176
+ }
177
+ return undefined;
178
+ }
179
+ createRenderer(context, rendererType = this.rendererType) {
49
180
  let renderer;
50
181
  switch (rendererType) {
51
182
  case Types_1.RendererType.WEBGL:
52
- renderer = new WebGLRenderer_1.WebGLRenderer(this.handleWebGLFallback(context).bind(this));
183
+ if (context.useWebCodecsDecoder) {
184
+ renderer = new WebCodecsRenderer_1.WebCodecsRenderer();
185
+ }
186
+ else {
187
+ renderer = new WebGLRenderer_1.WebGLRenderer(this.handleWebGLFallback(context).bind(this));
188
+ renderer.bind(context.view);
189
+ }
53
190
  break;
54
191
  case Types_1.RendererType.SOFTWARE:
55
192
  renderer = new YUVCanvasRenderer_1.YUVCanvasRenderer();
193
+ renderer.bind(context.view);
56
194
  break;
57
195
  default:
58
196
  throw new Error('Unknown renderer type');
59
197
  }
60
- renderer.bind(context.view);
61
- renderer.context = {
62
- renderMode: context.renderMode,
63
- mirrorMode: context.mirrorMode,
64
- };
198
+ renderer.setContext(context);
65
199
  return renderer;
66
200
  }
201
+ startRendering() {
202
+ if (this._renderingTimer)
203
+ return;
204
+ const renderingLooper = () => {
205
+ if (this._previousFirstFrameTime === 0) {
206
+ // Get the current time as the time of the first frame of per second
207
+ this._previousFirstFrameTime = performance.now();
208
+ // Reset the frame count
209
+ this._currentFrameCount = 0;
210
+ }
211
+ // Increase the frame count
212
+ ++this._currentFrameCount;
213
+ // Get the current time
214
+ const currentFrameTime = performance.now();
215
+ // Calculate the time difference between the current frame and the previous frame
216
+ const deltaTime = currentFrameTime - this._previousFirstFrameTime;
217
+ // Calculate the expected time of the current frame
218
+ const expectedTime = (this._currentFrameCount * 1000) / this.renderingFps;
219
+ (0, Utils_1.logDebug)(new Date().toLocaleTimeString(), 'currentFrameCount', this._currentFrameCount, 'expectedTime', expectedTime, 'deltaTime', deltaTime);
220
+ if (this._rendererCaches.length === 0) {
221
+ // If there is no renderer, stop rendering
222
+ this.stopRendering();
223
+ return;
224
+ }
225
+ // Render all renderers that do not use WebCodecs
226
+ for (const rendererCache of this._rendererCaches.filter((cache) => cache instanceof RendererCache_1.RendererCache)) {
227
+ this.doRendering(rendererCache);
228
+ }
229
+ if (this._currentFrameCount >= this.renderingFps) {
230
+ this._previousFirstFrameTime = 0;
231
+ }
232
+ if (deltaTime < expectedTime) {
233
+ // If the time difference between the current frame and the previous frame is less than the expected time, then wait for the difference
234
+ this._renderingTimer = window.setTimeout(renderingLooper, expectedTime - deltaTime);
235
+ }
236
+ else {
237
+ // If the time difference between the current frame and the previous frame is greater than the expected time, then render immediately
238
+ renderingLooper();
239
+ }
240
+ };
241
+ renderingLooper();
242
+ }
67
243
  doRendering(rendererCache) {
68
244
  rendererCache.draw();
69
245
  }
70
246
  handleWebGLFallback(context) {
71
247
  return (renderer) => {
72
- const { context: { renderMode, mirrorMode }, } = renderer;
73
248
  const renderers = this.getRenderers(context);
74
249
  renderer.unbind();
75
- const newRenderer = this.createRenderer({ ...context, renderMode, mirrorMode }, Types_1.RendererType.SOFTWARE);
250
+ const newRenderer = this.createRenderer(context, Types_1.RendererType.SOFTWARE);
76
251
  renderers.splice(renderers.indexOf(renderer), 1, newRenderer);
77
252
  };
78
253
  }
254
+ handleWebCodecsFallback(context) {
255
+ let engine = (0, AgoraSdk_1.default)();
256
+ engine.getMediaEngine().unregisterVideoEncodedFrameObserver({});
257
+ if (context.uid) {
258
+ if ((0, IRendererCache_1.isUseConnection)(context)) {
259
+ engine.setRemoteVideoSubscriptionOptionsEx(context.uid, {
260
+ type: AgoraBase_1.VideoStreamType.VideoStreamHigh,
261
+ encodedFrameOnly: false,
262
+ }, {
263
+ channelId: context.channelId,
264
+ localUid: context.localUid,
265
+ });
266
+ }
267
+ else {
268
+ engine.setRemoteVideoSubscriptionOptions(context.uid, {
269
+ type: AgoraBase_1.VideoStreamType.VideoStreamHigh,
270
+ encodedFrameOnly: false,
271
+ });
272
+ }
273
+ }
274
+ Utils_1.AgoraEnv.enableWebCodecsDecoder = false;
275
+ Utils_1.AgoraEnv.CapabilityManager?.setWebCodecsDecoderEnabled(false);
276
+ let renderers = this.getRenderers(context);
277
+ for (let renderer of renderers) {
278
+ this.addOrRemoveRenderer({
279
+ ...renderer.context,
280
+ setupMode: AgoraBase_1.VideoViewSetupMode.VideoViewSetupReplace,
281
+ });
282
+ }
283
+ }
284
+ stopRendering() {
285
+ if (this._renderingTimer) {
286
+ window.clearTimeout(this._renderingTimer);
287
+ this._renderingTimer = undefined;
288
+ }
289
+ }
290
+ setRendererContext(context) {
291
+ const checkedContext = this.presetRendererContext(context);
292
+ for (const rendererCache of this._rendererCaches) {
293
+ const result = rendererCache.setRendererContext(checkedContext);
294
+ if (result) {
295
+ return true;
296
+ }
297
+ }
298
+ return false;
299
+ }
79
300
  }
80
301
  exports.RendererManager = RendererManager;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebCodecsRenderer = void 0;
4
+ const Types_1 = require("../../Types");
5
+ const Utils_1 = require("../../Utils");
6
+ const IRenderer_1 = require("../IRenderer");
7
+ class WebCodecsRenderer extends IRenderer_1.IRenderer {
8
+ constructor() {
9
+ super();
10
+ this.rendererType = Types_1.RendererType.WEBCODECSRENDERER;
11
+ }
12
+ bind(element) {
13
+ super.bind(element);
14
+ if (!this.canvas)
15
+ return;
16
+ this.offscreenCanvas = this.canvas.transferControlToOffscreen();
17
+ this.gl = (0, Utils_1.getContextByCanvas)(this.offscreenCanvas);
18
+ if (!this.gl)
19
+ return;
20
+ const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
21
+ if (!vertexShader)
22
+ return;
23
+ this.gl.shaderSource(vertexShader, WebCodecsRenderer.vertexShaderSource);
24
+ this.gl.compileShader(vertexShader);
25
+ if (!this.gl.getShaderParameter(vertexShader, this.gl.COMPILE_STATUS)) {
26
+ throw this.gl.getShaderInfoLog(vertexShader);
27
+ }
28
+ const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
29
+ if (!fragmentShader)
30
+ return;
31
+ this.gl.shaderSource(fragmentShader, WebCodecsRenderer.fragmentShaderSource);
32
+ this.gl.compileShader(fragmentShader);
33
+ if (!this.gl.getShaderParameter(fragmentShader, this.gl.COMPILE_STATUS)) {
34
+ throw this.gl.getShaderInfoLog(fragmentShader);
35
+ }
36
+ const shaderProgram = this.gl.createProgram();
37
+ if (!shaderProgram)
38
+ return;
39
+ this.gl.attachShader(shaderProgram, vertexShader);
40
+ this.gl.attachShader(shaderProgram, fragmentShader);
41
+ this.gl.linkProgram(shaderProgram);
42
+ if (!this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS)) {
43
+ throw this.gl.getProgramInfoLog(shaderProgram);
44
+ }
45
+ this.gl.useProgram(shaderProgram);
46
+ // Vertex coordinates, clockwise from bottom-left.
47
+ const vertexBuffer = this.gl.createBuffer();
48
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer);
49
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, -1.0, +1.0, +1.0, +1.0, +1.0, -1.0]), this.gl.STATIC_DRAW);
50
+ const xyLocation = this.gl.getAttribLocation(shaderProgram, 'xy');
51
+ this.gl.vertexAttribPointer(xyLocation, 2, this.gl.FLOAT, false, 0, 0);
52
+ this.gl.enableVertexAttribArray(xyLocation);
53
+ // Create one texture to upload frames to.
54
+ const texture = this.gl.createTexture();
55
+ this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
56
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
57
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
58
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
59
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
60
+ }
61
+ drawFrame(frame, _codecConfig) {
62
+ if (!this.offscreenCanvas || !frame)
63
+ return;
64
+ this.offscreenCanvas.width = _codecConfig.codedWidth;
65
+ this.offscreenCanvas.height = _codecConfig.codedHeight;
66
+ this.updateRenderMode();
67
+ this.rotateCanvas({
68
+ rotation: _codecConfig.rotation,
69
+ });
70
+ if (!this.gl)
71
+ return;
72
+ if (this.gl) {
73
+ // Upload the frame.
74
+ this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, frame);
75
+ frame.close();
76
+ // Configure and clear the drawing area.
77
+ this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
78
+ this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
79
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT);
80
+ // Draw the frame.
81
+ this.gl.drawArrays(this.gl.TRIANGLE_FAN, 0, 4);
82
+ }
83
+ super.drawFrame();
84
+ this.getFps();
85
+ }
86
+ rotateCanvas({ rotation }) {
87
+ if (!this.offscreenCanvas || !this.canvas)
88
+ return;
89
+ this.canvas.style.transform += ` rotateZ(${rotation}deg)`;
90
+ }
91
+ }
92
+ exports.WebCodecsRenderer = WebCodecsRenderer;
93
+ WebCodecsRenderer.vertexShaderSource = `
94
+ attribute vec2 xy;
95
+ varying highp vec2 uv;
96
+ void main(void) {
97
+ gl_Position = vec4(xy, 0.0, 1.0);
98
+ // Map vertex coordinates (-1 to +1) to UV coordinates (0 to 1).
99
+ // UV coordinates are Y-flipped relative to vertex coordinates.
100
+ uv = vec2((1.0 + xy.x) / 2.0, (1.0 - xy.y) / 2.0);
101
+ }
102
+ `;
103
+ WebCodecsRenderer.fragmentShaderSource = `
104
+ varying highp vec2 uv;
105
+ uniform sampler2D texture;
106
+ void main(void) {
107
+ gl_FragColor = texture2D(texture, uv);
108
+ }
109
+ `;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebCodecsRendererCache = void 0;
7
+ const AgoraSdk_1 = __importDefault(require("../AgoraSdk"));
8
+ const index_1 = require("../Decoder/index");
9
+ const AgoraBase_1 = require("../Private/AgoraBase");
10
+ const IrisApiEngine_1 = require("../Private/internal/IrisApiEngine");
11
+ const Types_1 = require("../Types");
12
+ const Utils_1 = require("../Utils");
13
+ const IRendererCache_1 = require("./IRendererCache");
14
+ class WebCodecsRendererCache extends IRendererCache_1.IRendererCache {
15
+ constructor(context) {
16
+ super(context);
17
+ this._firstFrame = true;
18
+ this._engine = (0, AgoraSdk_1.default)();
19
+ this._decoder = new index_1.WebCodecsDecoder(this.renderers, this.onDecoderError.bind(this), context);
20
+ this.draw();
21
+ }
22
+ onDecoderError(e) {
23
+ (0, Utils_1.logInfo)('webCodecsDecoder decode failed, fallback to native decoder', e);
24
+ Utils_1.AgoraEnv.AgoraRendererManager?.handleWebCodecsFallback(this.cacheContext);
25
+ }
26
+ onEncodedVideoFrameReceived(...[data, buffer]) {
27
+ let _data;
28
+ try {
29
+ _data = JSON.parse(data) ?? {};
30
+ }
31
+ catch (e) {
32
+ _data = {};
33
+ }
34
+ if (Object.keys(_data).length === 0 ||
35
+ !this._decoder ||
36
+ this.cacheContext.uid !== _data.uid)
37
+ return;
38
+ if (this._firstFrame) {
39
+ for (let renderer of this.renderers) {
40
+ if (renderer.rendererType !== Types_1.RendererType.WEBCODECSRENDERER) {
41
+ continue;
42
+ }
43
+ renderer.bind(renderer.context.view);
44
+ }
45
+ try {
46
+ this._decoder.decoderConfigure(_data.videoEncodedFrameInfo);
47
+ }
48
+ catch (error) {
49
+ (0, Utils_1.logInfo)(error);
50
+ return;
51
+ }
52
+ this._firstFrame = false;
53
+ }
54
+ if (this.shouldFallback(_data.videoEncodedFrameInfo)) {
55
+ Utils_1.AgoraEnv.AgoraRendererManager?.handleWebCodecsFallback(this.cacheContext);
56
+ }
57
+ else {
58
+ this._decoder.decodeFrame(buffer, _data.videoEncodedFrameInfo, new Date().getTime());
59
+ }
60
+ }
61
+ draw() {
62
+ if ((0, IRendererCache_1.isUseConnection)(this.cacheContext)) {
63
+ this._engine?.setRemoteVideoSubscriptionOptionsEx(this.cacheContext.uid, {
64
+ type: AgoraBase_1.VideoStreamType.VideoStreamHigh,
65
+ encodedFrameOnly: true,
66
+ }, {
67
+ channelId: this.cacheContext.channelId,
68
+ localUid: this.cacheContext.localUid,
69
+ });
70
+ }
71
+ else {
72
+ this._engine?.setRemoteVideoSubscriptionOptions(this.cacheContext.uid, {
73
+ type: AgoraBase_1.VideoStreamType.VideoStreamHigh,
74
+ encodedFrameOnly: true,
75
+ });
76
+ }
77
+ IrisApiEngine_1.AgoraElectronBridge.OnEvent(`call_back_with_encoded_video_frame_${this.cacheContext.uid}`, (...params) => {
78
+ try {
79
+ this.onEncodedVideoFrameReceived(...params);
80
+ }
81
+ catch (e) {
82
+ console.error(e);
83
+ }
84
+ });
85
+ }
86
+ shouldFallback(frameInfo) {
87
+ let shouldFallback = false;
88
+ if (!frameInfo.codecType) {
89
+ shouldFallback = true;
90
+ (0, Utils_1.logInfo)('codecType is not supported, fallback to native decoder');
91
+ }
92
+ else {
93
+ const mapping = Utils_1.AgoraEnv.CapabilityManager?.frameCodecMapping[frameInfo.codecType];
94
+ if (mapping === undefined) {
95
+ shouldFallback = true;
96
+ (0, Utils_1.logInfo)('codecType is not supported, fallback to native decoder');
97
+ }
98
+ else if (mapping.minWidth >= frameInfo.width &&
99
+ mapping.minHeight >= frameInfo.height &&
100
+ mapping.maxWidth <= frameInfo.width &&
101
+ mapping.maxHeight <= frameInfo.height) {
102
+ shouldFallback = true;
103
+ (0, Utils_1.logInfo)('frame size is not supported, fallback to native decoder');
104
+ }
105
+ }
106
+ return shouldFallback;
107
+ }
108
+ release() {
109
+ IrisApiEngine_1.AgoraElectronBridge.UnEvent(`call_back_with_encoded_video_frame_${this.cacheContext.uid}`);
110
+ this._decoder?.release();
111
+ this._decoder = null;
112
+ super.release();
113
+ }
114
+ }
115
+ exports.WebCodecsRendererCache = WebCodecsRendererCache;