agora-electron-sdk 4.5.1 → 4.5.2-dev.1
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/CHANGELOG.md +21 -0
- package/js/Decoder/gpu-utils.js +74 -0
- package/js/Decoder/index.js +172 -0
- package/js/Private/AgoraBase.js +15 -3
- package/js/Private/extension/AgoraBaseExtension.js +1 -0
- package/js/Private/internal/IrisApiEngine.js +20 -7
- package/js/Private/internal/RtcEngineExInternal.js +31 -16
- package/js/Private/ipc/main.js +21 -0
- package/js/Private/ipc/renderer.js +21 -0
- package/js/Renderer/CapabilityManager.js +99 -0
- package/js/Renderer/IRenderer.js +40 -11
- package/js/Renderer/IRendererCache.js +75 -0
- package/js/Renderer/RendererCache.js +26 -63
- package/js/Renderer/RendererManager.js +259 -38
- package/js/Renderer/WebCodecsRenderer/index.js +109 -0
- package/js/Renderer/WebCodecsRendererCache.js +115 -0
- package/js/Renderer/WebGLRenderer/index.js +115 -67
- package/js/Renderer/YUVCanvasRenderer/index.js +5 -3
- package/js/Renderer/index.js +0 -1
- package/js/Types.js +51 -1
- package/js/Utils.js +47 -7
- package/package.json +28 -11
- package/scripts/checkElectron.js +4 -2
- package/scripts/download.js +105 -0
- package/scripts/downloadPrebuild.js +2 -1
- package/scripts/synclib.js +2 -2
- package/ts/Decoder/gpu-utils.ts +92 -0
- package/ts/Decoder/index.ts +206 -0
- package/ts/Private/AgoraBase.ts +18 -4
- package/ts/Private/IAgoraRtcEngine.ts +6 -7
- package/ts/Private/IAgoraRtcEngineEx.ts +2 -1
- package/ts/Private/extension/AgoraBaseExtension.ts +14 -1
- package/ts/Private/internal/IrisApiEngine.ts +21 -7
- package/ts/Private/internal/RtcEngineExInternal.ts +27 -8
- package/ts/Private/ipc/main.ts +22 -0
- package/ts/Private/ipc/renderer.ts +21 -0
- package/ts/Renderer/CapabilityManager.ts +126 -0
- package/ts/Renderer/IRenderer.ts +52 -17
- package/ts/Renderer/IRendererCache.ts +96 -0
- package/ts/Renderer/RendererCache.ts +42 -85
- package/ts/Renderer/RendererManager.ts +342 -52
- package/ts/Renderer/WebCodecsRenderer/index.ts +145 -0
- package/ts/Renderer/WebCodecsRendererCache.ts +137 -0
- package/ts/Renderer/WebGLRenderer/index.ts +153 -107
- package/ts/Renderer/YUVCanvasRenderer/index.ts +24 -22
- package/ts/Renderer/index.ts +0 -1
- package/ts/Types.ts +130 -7
- package/ts/Utils.ts +53 -7
- package/types/Decoder/gpu-utils.d.ts +21 -0
- package/types/Decoder/gpu-utils.d.ts.map +1 -0
- package/types/Decoder/index.d.ts +26 -0
- package/types/Decoder/index.d.ts.map +1 -0
- package/types/Private/AgoraBase.d.ts +18 -4
- package/types/Private/AgoraBase.d.ts.map +1 -1
- package/types/Private/IAgoraRtcEngine.d.ts +6 -7
- package/types/Private/IAgoraRtcEngine.d.ts.map +1 -1
- package/types/Private/IAgoraRtcEngineEx.d.ts +2 -1
- package/types/Private/IAgoraRtcEngineEx.d.ts.map +1 -1
- package/types/Private/extension/AgoraBaseExtension.d.ts +13 -1
- package/types/Private/extension/AgoraBaseExtension.d.ts.map +1 -1
- package/types/Private/internal/IrisApiEngine.d.ts +2 -0
- package/types/Private/internal/IrisApiEngine.d.ts.map +1 -1
- package/types/Private/internal/RtcEngineExInternal.d.ts +2 -0
- package/types/Private/internal/RtcEngineExInternal.d.ts.map +1 -1
- package/types/Private/ipc/main.d.ts +2 -0
- package/types/Private/ipc/main.d.ts.map +1 -0
- package/types/Private/ipc/renderer.d.ts +3 -0
- package/types/Private/ipc/renderer.d.ts.map +1 -0
- package/types/Renderer/CapabilityManager.d.ts +20 -0
- package/types/Renderer/CapabilityManager.d.ts.map +1 -0
- package/types/Renderer/IRenderer.d.ts +8 -7
- package/types/Renderer/IRenderer.d.ts.map +1 -1
- package/types/Renderer/IRendererCache.d.ts +26 -0
- package/types/Renderer/IRendererCache.d.ts.map +1 -0
- package/types/Renderer/RendererCache.d.ts +6 -18
- package/types/Renderer/RendererCache.d.ts.map +1 -1
- package/types/Renderer/RendererManager.d.ts +49 -15
- package/types/Renderer/RendererManager.d.ts.map +1 -1
- package/types/Renderer/WebCodecsRenderer/index.d.ts +14 -0
- package/types/Renderer/WebCodecsRenderer/index.d.ts.map +1 -0
- package/types/Renderer/WebCodecsRendererCache.d.ts +15 -0
- package/types/Renderer/WebCodecsRendererCache.d.ts.map +1 -0
- package/types/Renderer/WebGLRenderer/index.d.ts +5 -3
- package/types/Renderer/WebGLRenderer/index.d.ts.map +1 -1
- package/types/Renderer/YUVCanvasRenderer/index.d.ts +1 -1
- package/types/Renderer/YUVCanvasRenderer/index.d.ts.map +1 -1
- package/types/Renderer/index.d.ts +0 -1
- package/types/Renderer/index.d.ts.map +1 -1
- package/types/Types.d.ts +99 -8
- package/types/Types.d.ts.map +1 -1
- package/types/Utils.d.ts +4 -0
- package/types/Utils.d.ts.map +1 -1
- package/js/Renderer/IRendererManager.js +0 -229
- package/scripts/publishCN/common.sh +0 -19
- package/scripts/publishCN/rewrite-dep.sh +0 -22
- package/scripts/publishCN/rewrite-example.sh +0 -22
- package/ts/Renderer/IRendererManager.ts +0 -316
- package/types/Renderer/IRendererManager.d.ts +0 -56
- package/types/Renderer/IRendererManager.d.ts.map +0 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
|
|
3
|
+
import createAgoraRtcEngine from '../AgoraSdk';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
GpuInfo,
|
|
7
|
+
VideoDecodeAcceleratorSupportedProfile,
|
|
8
|
+
} from '../Decoder/gpu-utils';
|
|
9
|
+
import { VideoCodecType } from '../Private/AgoraBase';
|
|
10
|
+
import { IRtcEngineEx } from '../Private/IAgoraRtcEngineEx';
|
|
11
|
+
import { ipcSend } from '../Private/ipc/renderer';
|
|
12
|
+
|
|
13
|
+
import { IPCMessageType, VideoFallbackStrategy, codecMapping } from '../Types';
|
|
14
|
+
import { AgoraEnv, logError, logInfo } from '../Utils';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @ignore
|
|
18
|
+
*/
|
|
19
|
+
export class CapabilityManager {
|
|
20
|
+
gpuInfo: GpuInfo = new GpuInfo();
|
|
21
|
+
frameCodecMapping: {
|
|
22
|
+
[key in VideoCodecType]?: VideoDecodeAcceleratorSupportedProfile;
|
|
23
|
+
} = {};
|
|
24
|
+
webCodecsDecoderEnabled: boolean = AgoraEnv.enableWebCodecsDecoder;
|
|
25
|
+
private _engine: IRtcEngineEx;
|
|
26
|
+
|
|
27
|
+
setWebCodecsDecoderEnabled(enabled: boolean): void {
|
|
28
|
+
this.webCodecsDecoderEnabled = enabled;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
this._engine = createAgoraRtcEngine();
|
|
33
|
+
if (AgoraEnv.enableWebCodecsDecoder) {
|
|
34
|
+
this.getGpuInfo(() => {
|
|
35
|
+
if (
|
|
36
|
+
AgoraEnv.videoFallbackStrategy ===
|
|
37
|
+
VideoFallbackStrategy.PerformancePriority
|
|
38
|
+
) {
|
|
39
|
+
if (!this.isSupportedH265()) {
|
|
40
|
+
if (this.isSupportedH264()) {
|
|
41
|
+
this._engine.setParameters(
|
|
42
|
+
JSON.stringify({ 'che.video.h265_dec_enable': false })
|
|
43
|
+
);
|
|
44
|
+
logInfo(
|
|
45
|
+
'the videoFallbackStrategy is PerformancePriority, H265 is not supported, fallback to H264'
|
|
46
|
+
);
|
|
47
|
+
} else {
|
|
48
|
+
this.webCodecsDecoderEnabled = false;
|
|
49
|
+
logInfo(
|
|
50
|
+
'the videoFallbackStrategy is PerformancePriority, H264 and H265 are not supported, fallback to native decoder'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} else if (
|
|
55
|
+
AgoraEnv.videoFallbackStrategy ===
|
|
56
|
+
VideoFallbackStrategy.BandwidthPriority
|
|
57
|
+
) {
|
|
58
|
+
if (!this.isSupportedH265()) {
|
|
59
|
+
this.webCodecsDecoderEnabled = false;
|
|
60
|
+
logInfo(
|
|
61
|
+
'the videoFallbackStrategy is BandwidthPriority, H265 is not supported, fallback to native decoder'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public getGpuInfo(callback?: () => void): void {
|
|
70
|
+
//getGpuInfo and videoDecoder is not supported in electron version < 22.0.0
|
|
71
|
+
//@ts-ignore
|
|
72
|
+
if (semver.lt(process.versions.electron, '22.0.0')) {
|
|
73
|
+
logError(
|
|
74
|
+
'WebCodecsDecoder is not supported in electron version < 22.0.0, please upgrade electron to 22.0.0 or later.'
|
|
75
|
+
);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
//@ts-ignore
|
|
79
|
+
if (process.type === 'renderer') {
|
|
80
|
+
ipcSend(IPCMessageType.AGORA_IPC_GET_GPU_INFO)
|
|
81
|
+
.then((result) => {
|
|
82
|
+
this.gpuInfo.videoDecodeAcceleratorSupportedProfile = result;
|
|
83
|
+
this.webCodecsDecoderEnabled = (AgoraEnv.enableWebCodecsDecoder &&
|
|
84
|
+
this.gpuInfo.videoDecodeAcceleratorSupportedProfile.length > 0)!;
|
|
85
|
+
|
|
86
|
+
result.forEach((profile: VideoDecodeAcceleratorSupportedProfile) => {
|
|
87
|
+
const match = codecMapping.find((item) =>
|
|
88
|
+
profile.codec.includes(item.profile)
|
|
89
|
+
);
|
|
90
|
+
if (match) {
|
|
91
|
+
//Normally, the range of compatible widths and heights should be the same under the same codec.
|
|
92
|
+
//there is no need to differentiate between different profiles. This could be optimized in the future.
|
|
93
|
+
this.frameCodecMapping[match.type] = {
|
|
94
|
+
codec: match.codec,
|
|
95
|
+
minWidth: profile.minWidth,
|
|
96
|
+
minHeight: profile.minHeight,
|
|
97
|
+
maxWidth: profile.maxWidth,
|
|
98
|
+
maxHeight: profile.maxHeight,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
callback && callback();
|
|
103
|
+
})
|
|
104
|
+
.catch((error) => {
|
|
105
|
+
logError(
|
|
106
|
+
'Failed to get GPU info, please check if you are already import agora-electron-sdk in the main process.',
|
|
107
|
+
error
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
} else {
|
|
111
|
+
logError('This function only works in renderer process');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public isSupportedH264(): boolean {
|
|
116
|
+
return this.frameCodecMapping[VideoCodecType.VideoCodecH264] !== undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public isSupportedH265(): boolean {
|
|
120
|
+
return this.frameCodecMapping[VideoCodecType.VideoCodecH265] !== undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
release(): void {
|
|
124
|
+
AgoraEnv.enableWebCodecsDecoder = false;
|
|
125
|
+
}
|
|
126
|
+
}
|
package/ts/Renderer/IRenderer.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { VideoMirrorModeType } from '../Private/AgoraBase';
|
|
2
2
|
import { RenderModeType, VideoFrame } from '../Private/AgoraMediaBase';
|
|
3
|
-
import { RendererContext } from '../Types';
|
|
4
|
-
|
|
5
|
-
type Context = Pick<RendererContext, 'renderMode' | 'mirrorMode'>;
|
|
3
|
+
import { CodecConfigInfo, RendererContext, RendererType } from '../Types';
|
|
6
4
|
|
|
7
5
|
export abstract class IRenderer {
|
|
8
6
|
parentElement?: HTMLElement;
|
|
9
7
|
container?: HTMLElement;
|
|
10
8
|
canvas?: HTMLCanvasElement;
|
|
11
|
-
|
|
9
|
+
rendererType: RendererType | undefined;
|
|
10
|
+
context: RendererContext = {};
|
|
11
|
+
private _frameCount = 0;
|
|
12
|
+
private _startTime: number | null = null;
|
|
12
13
|
|
|
13
14
|
public bind(element: HTMLElement) {
|
|
14
15
|
this.parentElement = element;
|
|
@@ -43,30 +44,30 @@ export abstract class IRenderer {
|
|
|
43
44
|
this.parentElement = undefined;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
public drawFrame(
|
|
47
|
+
public drawFrame(
|
|
48
|
+
_videoFrame?: VideoFrame,
|
|
49
|
+
_codecConfig?: CodecConfigInfo
|
|
50
|
+
): void {
|
|
47
51
|
if (!this.canvas) return;
|
|
48
52
|
if (this.canvas.style.display !== '') {
|
|
49
53
|
this.canvas.style.display = '';
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
public
|
|
54
|
-
if (this.context.renderMode !== renderMode) {
|
|
55
|
-
this.context.renderMode = renderMode;
|
|
57
|
+
public setContext(context: RendererContext) {
|
|
58
|
+
if (this.context.renderMode !== context.renderMode) {
|
|
59
|
+
this.context.renderMode = context.renderMode;
|
|
56
60
|
this.updateRenderMode();
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
if (this.context.mirrorMode !== mirrorMode) {
|
|
60
|
-
this.context.mirrorMode = mirrorMode;
|
|
63
|
+
if (this.context.mirrorMode !== context.mirrorMode) {
|
|
64
|
+
this.context.mirrorMode = context.mirrorMode;
|
|
61
65
|
this.updateMirrorMode();
|
|
62
66
|
}
|
|
67
|
+
this.context = { ...this.context, ...context };
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
return this._context;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
protected updateRenderMode() {
|
|
70
|
+
protected updateRenderMode(): void {
|
|
70
71
|
if (!this.canvas || !this.container) return;
|
|
71
72
|
|
|
72
73
|
const { clientWidth, clientHeight } = this.container;
|
|
@@ -76,9 +77,8 @@ export abstract class IRenderer {
|
|
|
76
77
|
const canvasAspectRatio = width / height;
|
|
77
78
|
const widthScale = clientWidth / width;
|
|
78
79
|
const heightScale = clientHeight / height;
|
|
79
|
-
|
|
80
80
|
const isHidden =
|
|
81
|
-
this.context
|
|
81
|
+
this.context.renderMode === RenderModeType.RenderModeHidden;
|
|
82
82
|
|
|
83
83
|
let scale = 1;
|
|
84
84
|
// If container's aspect ratio is larger than canvas's aspect ratio
|
|
@@ -120,4 +120,39 @@ export abstract class IRenderer {
|
|
|
120
120
|
);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
+
|
|
124
|
+
public getFps(): number {
|
|
125
|
+
let fps = 0;
|
|
126
|
+
if (!this.context.enableFps || !this.container) {
|
|
127
|
+
return fps;
|
|
128
|
+
}
|
|
129
|
+
if (this._startTime == null) {
|
|
130
|
+
this._startTime = performance.now();
|
|
131
|
+
} else {
|
|
132
|
+
const elapsed = (performance.now() - this._startTime) / 1000;
|
|
133
|
+
fps = ++this._frameCount / elapsed;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let span = this.container.querySelector('span');
|
|
137
|
+
if (!span) {
|
|
138
|
+
span = document.createElement('span');
|
|
139
|
+
|
|
140
|
+
Object.assign(span.style, {
|
|
141
|
+
position: 'absolute',
|
|
142
|
+
bottom: '0',
|
|
143
|
+
left: '0',
|
|
144
|
+
zIndex: '10',
|
|
145
|
+
width: '55px',
|
|
146
|
+
background: '#fff',
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
this.container.style.position = 'relative';
|
|
150
|
+
|
|
151
|
+
this.container.appendChild(span);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
span.innerText = `fps: ${fps.toFixed(0)}`;
|
|
155
|
+
|
|
156
|
+
return fps;
|
|
157
|
+
}
|
|
123
158
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { RendererCacheContext, RendererContext } from '../Types';
|
|
2
|
+
|
|
3
|
+
import { IRenderer } from './IRenderer';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @ignore
|
|
7
|
+
*/
|
|
8
|
+
export function generateRendererCacheKey({
|
|
9
|
+
channelId,
|
|
10
|
+
uid,
|
|
11
|
+
sourceType,
|
|
12
|
+
}: RendererContext): string {
|
|
13
|
+
return `${channelId}_${uid}_${sourceType}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @ignore
|
|
18
|
+
*/
|
|
19
|
+
export function isUseConnection(context: RendererCacheContext): boolean {
|
|
20
|
+
// if RtcConnection is not undefined, then use connection
|
|
21
|
+
return !!context.channelId && context.localUid !== undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export abstract class IRendererCache {
|
|
25
|
+
renderers: IRenderer[];
|
|
26
|
+
cacheContext: RendererCacheContext;
|
|
27
|
+
|
|
28
|
+
constructor({
|
|
29
|
+
channelId,
|
|
30
|
+
uid,
|
|
31
|
+
useWebCodecsDecoder,
|
|
32
|
+
enableFps,
|
|
33
|
+
sourceType,
|
|
34
|
+
localUid,
|
|
35
|
+
position,
|
|
36
|
+
}: RendererContext) {
|
|
37
|
+
this.renderers = [];
|
|
38
|
+
this.cacheContext = {
|
|
39
|
+
channelId,
|
|
40
|
+
uid,
|
|
41
|
+
useWebCodecsDecoder,
|
|
42
|
+
enableFps,
|
|
43
|
+
sourceType,
|
|
44
|
+
localUid,
|
|
45
|
+
position,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public get key(): string {
|
|
50
|
+
return generateRendererCacheKey(this.cacheContext);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public abstract draw(): void;
|
|
54
|
+
|
|
55
|
+
public findRenderer(view: Element): IRenderer | undefined {
|
|
56
|
+
return this.renderers.find((renderer) => renderer.parentElement === view);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public addRenderer(renderer: IRenderer): void {
|
|
60
|
+
this.renderers.push(renderer);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Remove the specified renderer if it is specified, otherwise remove all renderers
|
|
65
|
+
*/
|
|
66
|
+
public removeRenderer(renderer?: IRenderer): void {
|
|
67
|
+
let start = 0;
|
|
68
|
+
let deleteCount = this.renderers.length;
|
|
69
|
+
if (renderer) {
|
|
70
|
+
start = this.renderers.indexOf(renderer);
|
|
71
|
+
if (start < 0) return;
|
|
72
|
+
deleteCount = 1;
|
|
73
|
+
}
|
|
74
|
+
this.renderers.splice(start, deleteCount).forEach((it) => it.unbind());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public setRendererContext(context: RendererContext): boolean {
|
|
78
|
+
if (context.view) {
|
|
79
|
+
const renderer = this.findRenderer(context.view);
|
|
80
|
+
if (renderer) {
|
|
81
|
+
renderer.setContext(context);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
} else {
|
|
86
|
+
this.renderers.forEach((it) => {
|
|
87
|
+
it.setContext(context);
|
|
88
|
+
});
|
|
89
|
+
return this.renderers.length > 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public release(): void {
|
|
94
|
+
this.removeRenderer();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
import { VideoFrame } from '../Private/AgoraMediaBase';
|
|
2
|
-
import {
|
|
2
|
+
import { AgoraElectronBridge } from '../Private/internal/IrisApiEngine';
|
|
3
|
+
|
|
4
|
+
import { RendererContext } from '../Types';
|
|
3
5
|
import { AgoraEnv, logDebug } from '../Utils';
|
|
4
6
|
|
|
5
7
|
import { IRenderer } from './IRenderer';
|
|
8
|
+
import { IRendererCache } from './IRendererCache';
|
|
6
9
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
uid,
|
|
10
|
-
sourceType,
|
|
11
|
-
}: RendererContext): string {
|
|
12
|
-
return `${channelId}_${uid}_${sourceType}`;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class RendererCache {
|
|
16
|
-
private _renderers: IRenderer[];
|
|
17
|
-
private _videoFrame: VideoFrame;
|
|
18
|
-
private _context: RendererCacheContext;
|
|
10
|
+
export class RendererCache extends IRendererCache {
|
|
11
|
+
private videoFrame: VideoFrame;
|
|
19
12
|
private _enabled: boolean;
|
|
20
13
|
|
|
21
|
-
constructor(
|
|
22
|
-
|
|
23
|
-
this.
|
|
14
|
+
constructor(context: RendererContext) {
|
|
15
|
+
super(context);
|
|
16
|
+
this.videoFrame = {
|
|
24
17
|
yBuffer: Buffer.alloc(0),
|
|
25
18
|
uBuffer: Buffer.alloc(0),
|
|
26
19
|
vBuffer: Buffer.alloc(0),
|
|
20
|
+
alphaBuffer: AgoraEnv.encodeAlpha ? Buffer.alloc(0) : undefined,
|
|
27
21
|
width: 0,
|
|
28
22
|
height: 0,
|
|
29
23
|
yStride: 0,
|
|
@@ -31,33 +25,9 @@ export class RendererCache {
|
|
|
31
25
|
vStride: 0,
|
|
32
26
|
rotation: 0,
|
|
33
27
|
};
|
|
34
|
-
this._context = { channelId, uid, sourceType, position };
|
|
35
28
|
this._enabled = false;
|
|
36
29
|
}
|
|
37
30
|
|
|
38
|
-
public get key(): string {
|
|
39
|
-
return generateRendererCacheKey(this._context);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public get renderers(): IRenderer[] {
|
|
43
|
-
return this._renderers;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
public get videoFrame(): VideoFrame {
|
|
47
|
-
return this._videoFrame;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public get context(): RendererCacheContext {
|
|
51
|
-
return this._context;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @deprecated Use renderers instead
|
|
56
|
-
*/
|
|
57
|
-
public get renders(): IRenderer[] {
|
|
58
|
-
return this.renderers;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
31
|
/**
|
|
62
32
|
* @deprecated Use videoFrame instead
|
|
63
33
|
*/
|
|
@@ -65,19 +35,15 @@ export class RendererCache {
|
|
|
65
35
|
return this.videoFrame;
|
|
66
36
|
}
|
|
67
37
|
|
|
68
|
-
private get bridge() {
|
|
69
|
-
return AgoraEnv.AgoraElectronBridge;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
38
|
private enable() {
|
|
73
39
|
if (this._enabled) return;
|
|
74
|
-
|
|
40
|
+
AgoraElectronBridge.EnableVideoFrameCache(this.cacheContext);
|
|
75
41
|
this._enabled = true;
|
|
76
42
|
}
|
|
77
43
|
|
|
78
44
|
private disable() {
|
|
79
45
|
if (!this._enabled) return;
|
|
80
|
-
|
|
46
|
+
AgoraElectronBridge.DisableVideoFrameCache(this.cacheContext);
|
|
81
47
|
this._enabled = false;
|
|
82
48
|
}
|
|
83
49
|
|
|
@@ -89,10 +55,13 @@ export class RendererCache {
|
|
|
89
55
|
}
|
|
90
56
|
}
|
|
91
57
|
|
|
92
|
-
|
|
93
|
-
let { ret, isNewFrame } =
|
|
94
|
-
this.
|
|
95
|
-
this.videoFrame
|
|
58
|
+
override draw() {
|
|
59
|
+
let { ret, isNewFrame } = AgoraElectronBridge.GetVideoFrame(
|
|
60
|
+
this.cacheContext,
|
|
61
|
+
this.videoFrame,
|
|
62
|
+
{
|
|
63
|
+
encodeAlpha: AgoraEnv.encodeAlpha,
|
|
64
|
+
}
|
|
96
65
|
);
|
|
97
66
|
|
|
98
67
|
switch (ret) {
|
|
@@ -104,8 +73,19 @@ export class RendererCache {
|
|
|
104
73
|
this.videoFrame.yBuffer = Buffer.alloc(yStride! * height!);
|
|
105
74
|
this.videoFrame.uBuffer = Buffer.alloc(uStride! * height!);
|
|
106
75
|
this.videoFrame.vBuffer = Buffer.alloc(vStride! * height!);
|
|
107
|
-
|
|
108
|
-
|
|
76
|
+
if (AgoraEnv.encodeAlpha) {
|
|
77
|
+
this.videoFrame.alphaBuffer = Buffer.alloc(
|
|
78
|
+
this.videoFrame.width! * this.videoFrame.height!
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const result = AgoraElectronBridge.GetVideoFrame(
|
|
83
|
+
this.cacheContext,
|
|
84
|
+
this.videoFrame,
|
|
85
|
+
{
|
|
86
|
+
encodeAlpha: AgoraEnv.encodeAlpha,
|
|
87
|
+
}
|
|
88
|
+
);
|
|
109
89
|
ret = result.ret;
|
|
110
90
|
isNewFrame = result.isNewFrame;
|
|
111
91
|
break;
|
|
@@ -114,6 +94,10 @@ export class RendererCache {
|
|
|
114
94
|
return;
|
|
115
95
|
}
|
|
116
96
|
|
|
97
|
+
if (!AgoraEnv.encodeAlpha) {
|
|
98
|
+
this.videoFrame.alphaBuffer = undefined;
|
|
99
|
+
}
|
|
100
|
+
|
|
117
101
|
if (isNewFrame) {
|
|
118
102
|
this.renderers.forEach((renderer) => {
|
|
119
103
|
renderer.drawFrame(this.videoFrame);
|
|
@@ -121,47 +105,20 @@ export class RendererCache {
|
|
|
121
105
|
}
|
|
122
106
|
}
|
|
123
107
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
public addRenderer(renderer: IRenderer): void {
|
|
129
|
-
this._renderers.push(renderer);
|
|
108
|
+
override addRenderer(renderer: IRenderer): void {
|
|
109
|
+
super.addRenderer(renderer);
|
|
130
110
|
this.shouldEnable();
|
|
131
111
|
}
|
|
132
112
|
|
|
133
113
|
/**
|
|
134
114
|
* Remove the specified renderer if it is specified, otherwise remove all renderers
|
|
135
115
|
*/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
let deleteCount = this._renderers.length;
|
|
139
|
-
if (renderer) {
|
|
140
|
-
start = this._renderers.indexOf(renderer);
|
|
141
|
-
if (start < 0) return;
|
|
142
|
-
deleteCount = 1;
|
|
143
|
-
}
|
|
144
|
-
this._renderers.splice(start, deleteCount).forEach((it) => it.unbind());
|
|
116
|
+
override removeRenderer(renderer?: IRenderer): void {
|
|
117
|
+
super.removeRenderer(renderer);
|
|
145
118
|
this.shouldEnable();
|
|
146
119
|
}
|
|
147
120
|
|
|
148
|
-
public
|
|
149
|
-
|
|
150
|
-
renderMode,
|
|
151
|
-
mirrorMode,
|
|
152
|
-
}: RendererContext): boolean {
|
|
153
|
-
if (view) {
|
|
154
|
-
const renderer = this.findRenderer(view);
|
|
155
|
-
if (renderer) {
|
|
156
|
-
renderer.context = { renderMode, mirrorMode };
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
return false;
|
|
160
|
-
} else {
|
|
161
|
-
this._renderers.forEach((it) => {
|
|
162
|
-
it.context = { renderMode, mirrorMode };
|
|
163
|
-
});
|
|
164
|
-
return this._renderers.length > 0;
|
|
165
|
-
}
|
|
121
|
+
public release(): void {
|
|
122
|
+
super.release();
|
|
166
123
|
}
|
|
167
124
|
}
|