senza-sdk 4.4.4 → 4.4.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "senza-sdk",
3
- "version": "4.4.4",
3
+ "version": "4.4.6",
4
4
  "main": "./src/api.js",
5
5
  "description": "API for Senza application",
6
6
  "license": "MIT",
@@ -23,17 +23,18 @@
23
23
  "version:output": "echo 'export const version = \"'$npm_package_version'\";' > src/interface/version.js"
24
24
  },
25
25
  "devDependencies": {
26
- "@babel/cli": "^7.13.16",
27
- "@babel/core": "7.18.6",
28
- "@babel/plugin-transform-modules-commonjs": "^7.16.8",
29
- "@babel/preset-env": "^7.14.1",
26
+ "@babel/cli": "^7.22.0",
27
+ "@babel/core": "^7.22.0",
28
+ "@babel/plugin-transform-modules-commonjs": "^7.22.0",
29
+ "@babel/preset-env": "^7.22.0",
30
30
  "@eslint/eslintrc": "^3.3.0",
31
31
  "@eslint/js": "^9.22.0",
32
- "babel-jest": "^27.5.1",
32
+ "babel-jest": "^30.2.0",
33
33
  "eslint": "^9.22.0",
34
34
  "eslint-plugin-jest": "^28.11.0",
35
35
  "globals": "^16.0.0",
36
- "jest": "^27.5.1",
36
+ "jest": "^30.2.0",
37
+ "jest-environment-jsdom" : "^30.2.0",
37
38
  "jsdoc-to-markdown": "^7.1.1",
38
39
  "webpack": "^5.72.1",
39
40
  "webpack-cli": "^5.1.4"
@@ -6,6 +6,7 @@ import { remotePlayer } from "./remotePlayer.js";
6
6
  import { deviceManager } from "./deviceManager.js";
7
7
  import { displayManager } from "./displayManager.js";
8
8
  import { messageManager } from "./messageManager.js";
9
+ import { backgroundRenderControl } from "./backgroundRenderControl.js";
9
10
 
10
11
  export { remotePlayer };
11
12
  export { lifecycle };
@@ -141,6 +142,7 @@ export async function init(interfaceApiVersion, showSequenceFunc, initSequenceFu
141
142
  await remotePlayer._init(sessionInfoObj, triggerEvent);
142
143
  alarmManager._init();
143
144
  messageManager._init();
145
+ backgroundRenderControl._init();
144
146
  await displayManager._init();
145
147
  sdkLogger.log("All submodules initialized");
146
148
 
@@ -0,0 +1,113 @@
1
+ import { lifecycle } from "./lifecycle.js";
2
+ import { sdkLogger } from "./utils.js";
3
+ import { sessionInfo } from "./SessionInfo";
4
+
5
+ /**
6
+ * Internal background render control.
7
+ * Listens to lifecycle state changes and disables animation / video rendering when in background mode.
8
+ * Specifically it pauses CSS animations and hides video elements to reduce CPU/GPU load
9
+ *
10
+ * For remote-gpu deployments this reduces the CPU use in background mode from 6 cores to 0.4 cores.
11
+ *
12
+ * Extra CPU can be saved by also overriding requestAnimationFrame and slowing down time.
13
+ * This has the effect of ensuring the segments are downloaded at a slower pace
14
+ * - or not at all if you actually pause video, but these may have more complicated state and audio sync issues.
15
+ * Either way if you slow the decoding speed then we save more CPU by not doing as much SW video decoding,
16
+ * but the bulk is saved by the hidden video elements.
17
+ * See comments on https://jira01.engit.synamedia.com/browse/HSDEV-16827 for more about a PoC / spike that did this.
18
+ *
19
+ * As it stands, the current implementation that gets us 0.4 cores in background mode for remote-gpu is a good compromise of complexity vs benefit.
20
+ * It also roughly matches GPU mode background CPU use (maybe slightly better).
21
+ * GPU mode with this feature enabled (from my testing) saves about 0.15 cores ~0.45 -> ~0.30 cores
22
+ *
23
+ * This module uses the following settings:
24
+ * {
25
+ * "ui-streamer": {
26
+ * "throttleRenderingInBackground": {
27
+ * "enabled": true, // enable or disable the feature
28
+ * }
29
+ * }
30
+ * }
31
+ */
32
+ class BackgroundRenderControl {
33
+
34
+ /** initialised
35
+ * @type {boolean}
36
+ * @private
37
+ * Whether the instance has been initialized.
38
+ */
39
+ _initialized = false;
40
+
41
+ /**
42
+ * @type {boolean}
43
+ * @private
44
+ * Whether render control is enabled.
45
+ */
46
+ _enabled = false;
47
+
48
+ /**
49
+ * @type {boolean}
50
+ * @private
51
+ * Whether rendering is currently active.
52
+ */
53
+ _active = true;
54
+
55
+ /** @type {string|null}
56
+ * @private
57
+ * Stores the last known lifecycle state.
58
+ */
59
+ _lastState = null;
60
+
61
+ /** @type {Function}
62
+ * @private
63
+ * Event listener for lifecycle state changes.
64
+ */
65
+ _listener = (e) => this._handleStateChange(e.state);
66
+
67
+ _init() {
68
+ if (this._initialized) return;
69
+ this._enabled = sessionInfo?.sessionInfoObj.settings?.["ui-streamer"]?.throttleRenderingInBackground?.enabled ?? false;
70
+ sdkLogger.log(`Initializing BackgroundRenderControl: enabled=${this._enabled}`);
71
+ if (!this._enabled) return;
72
+ this._lastState = lifecycle.state;
73
+ lifecycle.addEventListener("onstatechange", this._listener);
74
+ this._initialized = true;
75
+ }
76
+
77
+ _handleStateChange(state) {
78
+ if (!this._enabled) return;
79
+ if (state === this._lastState) return;
80
+ this._lastState = state;
81
+ try {
82
+ if (state === lifecycle.UiState.FOREGROUND) this._onForeground();
83
+ else if (state === lifecycle.UiState.BACKGROUND) this._onBackground();
84
+ } catch (err) {
85
+ sdkLogger.error("BackgroundRenderControl state handling error", err);
86
+ }
87
+ }
88
+
89
+ _onForeground() {
90
+ if (this._active) return;
91
+ sdkLogger.log("BackgroundRenderControl resume rendering");
92
+ this._active = true;
93
+ const style = document.getElementById("hs-sdk-bg-render-styles");
94
+ if (style) style.remove();
95
+ }
96
+
97
+ _onBackground() {
98
+ if (!this._active) return;
99
+ sdkLogger.log("BackgroundRenderControl throttle rendering");
100
+ this._active = false;
101
+ if (!document.getElementById("hs-sdk-bg-render-styles")) {
102
+ const style = document.createElement("style");
103
+ style.id = "hs-sdk-bg-render-styles";
104
+ style.textContent = `
105
+ * { animation-play-state: paused !important; transition: none !important; scroll-behavior: auto !important; }
106
+ canvas, video, img { visibility: hidden !important; }
107
+ `;
108
+ document.head.appendChild(style);
109
+ }
110
+ }
111
+ }
112
+
113
+ export const backgroundRenderControl = new BackgroundRenderControl();