@camstack/addon-pipeline 1.1.28 → 1.1.29
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/dist/audio-analyzer/index.js +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/audio-codec-ffmpeg/index.js +1 -5
- package/dist/audio-codec-ffmpeg/index.mjs +1 -5
- package/dist/decoder-ffmpeg/index.js +102 -352
- package/dist/decoder-ffmpeg/index.mjs +82 -332
- package/dist/decoder-nodeav/index.js +6 -4
- package/dist/decoder-nodeav/index.mjs +6 -4
- package/dist/detection-pipeline/index.js +204 -180
- package/dist/detection-pipeline/index.mjs +204 -180
- package/dist/{dist-Biq62zt4.js → dist-Cwc0TUQr.js} +7 -42
- package/dist/{dist-C6_wgXqF.mjs → dist-DjuGmyG9.mjs} +7 -42
- package/dist/ffmpeg-args-C5GPp8Cw.mjs +323 -0
- package/dist/ffmpeg-args-D6h1edXK.js +418 -0
- package/dist/frame-dropper-AjheBGMG.mjs +22 -0
- package/dist/frame-dropper-DKLM6pMz.js +27 -0
- package/dist/{frame-handle-plane-BIoY6nRV.mjs → frame-handle-plane-Bkxz-TTD.mjs} +1 -1
- package/dist/{frame-handle-plane-D6BzyEgy.js → frame-handle-plane-DQNCTrpC.js} +1 -1
- package/dist/{frame-ring-sink-9J0wCdLF.js → frame-ring-sink-8LLV-cvH.js} +1 -1
- package/dist/{frame-ring-sink-Cs9vby6v.mjs → frame-ring-sink-ClEWjiRU.mjs} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +2 -2
- package/dist/pipeline-runner/index.mjs +2 -2
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DoReAb4y.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D567z31g.mjs} +3 -3
- package/dist/stream-broker/{hostInit-C0SuwQhL.mjs → hostInit-B_b3PIZB.mjs} +3 -3
- package/dist/stream-broker/index.js +168 -121
- package/dist/stream-broker/index.mjs +159 -112
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Br2yi8ah.js → MaskShapeCanvas-DI4BY7W2-x-DZOuQL.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-BSCcPdPf.js → MotionZonesSettings-NcxxQN8r-DTeuDGCU.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-ztxvxSjS.js → PrivacyMaskSettings-APgPLF7p-CirtxO3e.js} +1 -1
- package/embed-dist/assets/{index-CeZV1B-2.js → index-CpUy8OIE.js} +9 -9
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
- package/dist/frame-dropper-7RTo_YyG.js +0 -68
- package/dist/frame-dropper-CwkBTPGV.mjs +0 -51
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __require } from "../chunk-BdkLduGY.mjs";
|
|
2
|
-
import { $ as sleep, B as errMsg, E as hfModelUrl, F as runtimeDevices$1, G as EventCategory, K as createEvent, M as pipelineExecutorCapability, R as supportedRuntimes$1, S as defaultDeviceFor$1, T as evaluateZoneRules, V as BaseAddon, X as parseJsonUnknown, a as COCO_TO_MACRO, i as COCO_80_LABELS,
|
|
2
|
+
import { $ as sleep, B as errMsg, E as hfModelUrl, F as runtimeDevices$1, G as EventCategory, K as createEvent, M as pipelineExecutorCapability, R as supportedRuntimes$1, S as defaultDeviceFor$1, T as evaluateZoneRules, V as BaseAddon, X as parseJsonUnknown, a as COCO_TO_MACRO, i as COCO_80_LABELS, m as YAMNET_TO_MACRO, q as hydrateSchema, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, w as detectionPipelineCapability } from "../dist-DjuGmyG9.mjs";
|
|
3
3
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
4
4
|
import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-BPy6aoAx.mjs";
|
|
5
5
|
import { FrameRingReaderCache } from "@camstack/shm-ring";
|
|
@@ -8,87 +8,6 @@ import * as path$1 from "node:path";
|
|
|
8
8
|
import * as os from "node:os";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import sharp from "sharp";
|
|
11
|
-
//#region src/detection-pipeline/engine-store-keys.ts
|
|
12
|
-
/**
|
|
13
|
-
* Per-node scoping for the detection-pipeline engine cascade.
|
|
14
|
-
*
|
|
15
|
-
* The detection addon's settings store is a single CLUSTER-SHARED blob (the
|
|
16
|
-
* settings-store cap is hub-resident; every node's detection instance reads and
|
|
17
|
-
* writes the same keys). That is correct for node-agnostic settings (pipeline
|
|
18
|
-
* steps, tuning) but WRONG for the engine cascade — `engineBackend` /
|
|
19
|
-
* `engineDevice` / `probedBestEngine` are hardware-specific, so the hub (NPU)
|
|
20
|
-
* and a remote agent (iGPU, or no accelerator at all) must hold INDEPENDENT
|
|
21
|
-
* selections. Sharing them lets one node's pick (e.g. `openvino/npu`) override
|
|
22
|
-
* another node that has no NPU.
|
|
23
|
-
*
|
|
24
|
-
* These three keys are therefore persisted node-scoped as `<key>@<nodeId>`.
|
|
25
|
-
* Everything else in the store stays shared. There is NO fallback to a legacy
|
|
26
|
-
* un-scoped value for ANY node (the hub included) and no in-code migration: a
|
|
27
|
-
* bare key (written before scoping, or by an older build) is inert — invisible
|
|
28
|
-
* to every node. A node with no scoped key reads `undefined`, which drives its
|
|
29
|
-
* OWN platform auto-pick (`autoPickAndPersist` / `reprobeEngine` persist the
|
|
30
|
-
* node's own probe under `<key>@<node>`). Serving a bare value to any node
|
|
31
|
-
* would leak one node's hardware pick (e.g. `openvino/auto`) onto a node that
|
|
32
|
-
* cannot run it (the CB3 "Mac runs OpenVINO" / N100 AUTO-device bug). This
|
|
33
|
-
* mirrors the decoder's `readNodeDecoderBackend` no-fallback rule.
|
|
34
|
-
*/
|
|
35
|
-
var ENGINE_CASCADE_KEYS = [
|
|
36
|
-
"engineBackend",
|
|
37
|
-
"engineDevice",
|
|
38
|
-
"probedBestEngine"
|
|
39
|
-
];
|
|
40
|
-
function isEngineCascadeKey(key) {
|
|
41
|
-
return ENGINE_CASCADE_KEYS.includes(key);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Normalise a raw kernel node id to the bare node id used for scoping.
|
|
45
|
-
* `localNodeId` can carry a `<node>/<addon>` suffix; the engine selection is
|
|
46
|
-
* per-NODE, so strip the addon segment. Falls back to `hub`.
|
|
47
|
-
*/
|
|
48
|
-
function normalizeEngineNodeId(rawNodeId) {
|
|
49
|
-
const raw = rawNodeId ?? "hub";
|
|
50
|
-
return raw.includes("/") ? raw.split("/")[0] ?? "hub" : raw;
|
|
51
|
-
}
|
|
52
|
-
/** The node-scoped store key for an engine cascade field. */
|
|
53
|
-
function nodeEngineKey(base, nodeId) {
|
|
54
|
-
return `${base}@${normalizeEngineNodeId(nodeId)}`;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Read an engine cascade value for a node: the node-scoped key if present,
|
|
58
|
-
* otherwise `undefined` — for EVERY node, the hub included. There is no
|
|
59
|
-
* fallback to the legacy un-scoped key: a bare value in the store is inert.
|
|
60
|
-
* A node with no scoped key gets `undefined` so its own platform-driven
|
|
61
|
-
* auto-pick runs and persists a real per-node selection under `<key>@<node>`.
|
|
62
|
-
* (A bare fallback would leak one node's engine selection cluster-wide — CB3.)
|
|
63
|
-
*/
|
|
64
|
-
function readNodeEngineValue(store, base, nodeId) {
|
|
65
|
-
return store[nodeEngineKey(base, nodeId)];
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Project a raw store onto the plain engine cascade keys for THIS node, so the
|
|
69
|
-
* UI schema (whose field keys are the bare `engineBackend` etc.) hydrates from
|
|
70
|
-
* the node's own selection. Non-engine keys are left untouched. Node-scoped
|
|
71
|
-
* keys for OTHER nodes are dropped from the projection (not relevant to this
|
|
72
|
-
* node's form).
|
|
73
|
-
*/
|
|
74
|
-
function projectNodeEngine(store, nodeId) {
|
|
75
|
-
const out = {};
|
|
76
|
-
const scopedForAnyNode = /* @__PURE__ */ new Set();
|
|
77
|
-
for (const key of Object.keys(store)) {
|
|
78
|
-
const atIdx = key.indexOf("@");
|
|
79
|
-
if (isEngineCascadeKey(atIdx >= 0 ? key.slice(0, atIdx) : key)) {
|
|
80
|
-
scopedForAnyNode.add(key);
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
out[key] = store[key];
|
|
84
|
-
}
|
|
85
|
-
for (const base of ENGINE_CASCADE_KEYS) {
|
|
86
|
-
const value = readNodeEngineValue(store, base, nodeId);
|
|
87
|
-
if (value !== void 0) out[base] = value;
|
|
88
|
-
}
|
|
89
|
-
return out;
|
|
90
|
-
}
|
|
91
|
-
//#endregion
|
|
92
11
|
//#region src/detection-pipeline/runtimes.ts
|
|
93
12
|
var KNOWN_PLATFORMS = [
|
|
94
13
|
"darwin",
|
|
@@ -260,6 +179,88 @@ function pickBestRuntime(env, bestBackendHint) {
|
|
|
260
179
|
};
|
|
261
180
|
}
|
|
262
181
|
//#endregion
|
|
182
|
+
//#region src/detection-pipeline/engine-store-keys.ts
|
|
183
|
+
/**
|
|
184
|
+
* Per-node scoping for the detection-pipeline engine cascade.
|
|
185
|
+
*
|
|
186
|
+
* The detection addon's settings store is a single CLUSTER-SHARED blob (the
|
|
187
|
+
* settings-store cap is hub-resident; every node's detection instance reads and
|
|
188
|
+
* writes the same keys). That is correct for node-agnostic settings (pipeline
|
|
189
|
+
* steps, tuning) but WRONG for the engine cascade — `engineBackend` /
|
|
190
|
+
* `engineDevice` / `probedBestEngine` are hardware-specific, so the hub (NPU)
|
|
191
|
+
* and a remote agent (iGPU, or no accelerator at all) must hold INDEPENDENT
|
|
192
|
+
* selections. Sharing them lets one node's pick (e.g. `openvino/npu`) override
|
|
193
|
+
* another node that has no NPU.
|
|
194
|
+
*
|
|
195
|
+
* These three keys are therefore persisted node-scoped as `<key>@<nodeId>`.
|
|
196
|
+
* Everything else in the store stays shared. There is NO fallback to a legacy
|
|
197
|
+
* un-scoped value for ANY node (the hub included) and no in-code migration: a
|
|
198
|
+
* bare key (written before scoping, or by an older build) is inert — invisible
|
|
199
|
+
* to every node. A node with no scoped key reads `undefined`, which drives its
|
|
200
|
+
* OWN live resolve (`resolveAutoEngine` picks the node's runtime from the local
|
|
201
|
+
* kernel each boot; `reprobeEngine` persists an explicit probe under
|
|
202
|
+
* `<key>@<node>`). Serving a bare value to any node
|
|
203
|
+
* would leak one node's hardware pick (e.g. `openvino/auto`) onto a node that
|
|
204
|
+
* cannot run it (the CB3 "Mac runs OpenVINO" / N100 AUTO-device bug). This
|
|
205
|
+
* mirrors the decoder's `readNodeDecoderBackend` no-fallback rule.
|
|
206
|
+
*/
|
|
207
|
+
var ENGINE_CASCADE_KEYS = [
|
|
208
|
+
"engineBackend",
|
|
209
|
+
"engineDevice",
|
|
210
|
+
"probedBestEngine"
|
|
211
|
+
];
|
|
212
|
+
function isEngineCascadeKey(key) {
|
|
213
|
+
return ENGINE_CASCADE_KEYS.includes(key);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Normalise a raw kernel node id to the bare node id used for scoping.
|
|
217
|
+
* `localNodeId` can carry a `<node>/<addon>` suffix; the engine selection is
|
|
218
|
+
* per-NODE, so strip the addon segment. Falls back to `hub`.
|
|
219
|
+
*/
|
|
220
|
+
function normalizeEngineNodeId(rawNodeId) {
|
|
221
|
+
const raw = rawNodeId ?? "hub";
|
|
222
|
+
return raw.includes("/") ? raw.split("/")[0] ?? "hub" : raw;
|
|
223
|
+
}
|
|
224
|
+
/** The node-scoped store key for an engine cascade field. */
|
|
225
|
+
function nodeEngineKey(base, nodeId) {
|
|
226
|
+
return `${base}@${normalizeEngineNodeId(nodeId)}`;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Read an engine cascade value for a node: the node-scoped key if present,
|
|
230
|
+
* otherwise `undefined` — for EVERY node, the hub included. There is no
|
|
231
|
+
* fallback to the legacy un-scoped key: a bare value in the store is inert.
|
|
232
|
+
* A node with no scoped key gets `undefined` so its own platform-driven
|
|
233
|
+
* auto-pick runs and persists a real per-node selection under `<key>@<node>`.
|
|
234
|
+
* (A bare fallback would leak one node's engine selection cluster-wide — CB3.)
|
|
235
|
+
*/
|
|
236
|
+
function readNodeEngineValue(store, base, nodeId) {
|
|
237
|
+
return store[nodeEngineKey(base, nodeId)];
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Project a raw store onto the plain engine cascade keys for THIS node, so the
|
|
241
|
+
* UI schema (whose field keys are the bare `engineBackend` etc.) hydrates from
|
|
242
|
+
* the node's own selection. Non-engine keys are left untouched. Node-scoped
|
|
243
|
+
* keys for OTHER nodes are dropped from the projection (not relevant to this
|
|
244
|
+
* node's form).
|
|
245
|
+
*/
|
|
246
|
+
function projectNodeEngine(store, nodeId) {
|
|
247
|
+
const out = {};
|
|
248
|
+
const scopedForAnyNode = /* @__PURE__ */ new Set();
|
|
249
|
+
for (const key of Object.keys(store)) {
|
|
250
|
+
const atIdx = key.indexOf("@");
|
|
251
|
+
if (isEngineCascadeKey(atIdx >= 0 ? key.slice(0, atIdx) : key)) {
|
|
252
|
+
scopedForAnyNode.add(key);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
out[key] = store[key];
|
|
256
|
+
}
|
|
257
|
+
for (const base of ENGINE_CASCADE_KEYS) {
|
|
258
|
+
const value = readNodeEngineValue(store, base, nodeId);
|
|
259
|
+
if (value !== void 0) out[base] = value;
|
|
260
|
+
}
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
//#endregion
|
|
263
264
|
//#region src/detection-pipeline/engine/shared-inference-pool.ts
|
|
264
265
|
/**
|
|
265
266
|
* SharedInferencePool — TypeScript wrapper for inference_pool.py.
|
|
@@ -4572,56 +4573,53 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4572
4573
|
error: errMsg(err)
|
|
4573
4574
|
} });
|
|
4574
4575
|
}
|
|
4575
|
-
await this.
|
|
4576
|
+
await this.resolveAutoEngine();
|
|
4576
4577
|
this.needsAutoPick = false;
|
|
4577
4578
|
this.startProvisioningForCurrentEngine();
|
|
4578
4579
|
}
|
|
4579
4580
|
/**
|
|
4580
|
-
*
|
|
4581
|
-
*
|
|
4582
|
-
*
|
|
4581
|
+
* Resolve the `'auto'` engine LIVE from this node's own kernel inference
|
|
4582
|
+
* resolver (`ctx.kernel.inferenceEngine`) — the runtime mirror of
|
|
4583
|
+
* `ctx.kernel.hwaccel`. Each node (hub + forked worker + remote agent)
|
|
4584
|
+
* resolves its OWN accelerators in-process, so a forked agent child never
|
|
4585
|
+
* adopts the hub's runtime from the `platform-probe` singleton.
|
|
4583
4586
|
*
|
|
4584
|
-
*
|
|
4585
|
-
*
|
|
4586
|
-
*
|
|
4587
|
-
*
|
|
4588
|
-
*
|
|
4589
|
-
*
|
|
4590
|
-
* accelerator surfaces. In that case we set the in-memory floor for liveness
|
|
4591
|
-
* but leave the store untouched so the next boot re-attempts the pick.
|
|
4587
|
+
* NEVER persists. `'auto'` is a live-resolved sentinel: the pick is recomputed
|
|
4588
|
+
* every boot from the local hardware, so it is inherently self-healing — the
|
|
4589
|
+
* old `autoPickAndPersist` sticky-onnx bug (a premature onnx pick persisted
|
|
4590
|
+
* during a boot race, then locked forever) cannot recur because the store is
|
|
4591
|
+
* never written here. Only an explicit operator override is persisted, and
|
|
4592
|
+
* that write happens through the settings UI, not this path.
|
|
4592
4593
|
*/
|
|
4593
|
-
async
|
|
4594
|
+
async resolveAutoEngine() {
|
|
4594
4595
|
let hardware = null;
|
|
4595
4596
|
try {
|
|
4596
|
-
|
|
4597
|
-
if (api) hardware = (await api.platformProbe.getCapabilities.query({ nodeId: this.localProbeNodeId() }))?.hardware ?? null;
|
|
4597
|
+
hardware = await this.addonCtx?.kernel?.inferenceEngine?.resolveHardware() ?? null;
|
|
4598
4598
|
} catch {}
|
|
4599
|
-
const pick = pickBestRuntime(runtimeEnvFromProcess(toProbedHardware(hardware)), null);
|
|
4600
|
-
|
|
4599
|
+
const pick = pickBestRuntime(runtimeEnvFromProcess(hardware ? toProbedHardware(hardware) : null), null);
|
|
4600
|
+
this.currentEngine = {
|
|
4601
4601
|
runtime: "python",
|
|
4602
4602
|
backend: pick.runtimeId,
|
|
4603
4603
|
format: modelFormatFor(pick.runtimeId),
|
|
4604
4604
|
device: pick.device
|
|
4605
4605
|
};
|
|
4606
|
-
this.
|
|
4607
|
-
if (!(pick.runtimeId !== "onnx" || hardware !== null)) {
|
|
4608
|
-
this.log.info("Auto-pick: onnx floor pending gpu probe — NOT persisting (next boot retries)", { meta: {
|
|
4609
|
-
backend: pick.runtimeId,
|
|
4610
|
-
device: pick.device
|
|
4611
|
-
} });
|
|
4612
|
-
return;
|
|
4613
|
-
}
|
|
4614
|
-
const apNode = this.localProbeNodeId();
|
|
4615
|
-
await this.writeStore({
|
|
4616
|
-
[nodeEngineKey("engineBackend", apNode)]: pick.runtimeId,
|
|
4617
|
-
[nodeEngineKey("engineDevice", apNode)]: pick.device
|
|
4618
|
-
});
|
|
4619
|
-
this.log.info("Auto-picked engine (platform-deterministic)", { meta: {
|
|
4606
|
+
this.log.info("Resolved auto engine (local kernel)", { meta: {
|
|
4620
4607
|
backend: pick.runtimeId,
|
|
4621
4608
|
device: pick.device,
|
|
4622
|
-
|
|
4609
|
+
hadHardware: hardware !== null
|
|
4623
4610
|
} });
|
|
4624
4611
|
}
|
|
4612
|
+
/**
|
|
4613
|
+
* The RUNTIME that `'auto'` actually resolved to on this node (the live
|
|
4614
|
+
* `currentEngine.backend`), narrowed to a {@link RuntimeId}. The addon feeds
|
|
4615
|
+
* this into `resolveBackendTuning` when the stored config is `'auto'`, so the
|
|
4616
|
+
* pool tuning + respawn detection track the RESOLVED backend rather than the
|
|
4617
|
+
* `'auto'` sentinel (which would otherwise floor to onnx tuning).
|
|
4618
|
+
*/
|
|
4619
|
+
resolvedEngineBackend() {
|
|
4620
|
+
const backend = this.currentEngine.backend;
|
|
4621
|
+
return backend === "openvino" || backend === "coreml" ? backend : "onnx";
|
|
4622
|
+
}
|
|
4625
4623
|
/** Map a backend string to a known RuntimeId, flooring to onnx. */
|
|
4626
4624
|
toRuntimeId(backend) {
|
|
4627
4625
|
return [
|
|
@@ -4695,6 +4693,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4695
4693
|
const prev = this.currentEngine;
|
|
4696
4694
|
const stored = await this.loadEngine();
|
|
4697
4695
|
if (stored) this.currentEngine = stored;
|
|
4696
|
+
else await this.resolveAutoEngine();
|
|
4698
4697
|
if ((prev.runtime !== this.currentEngine.runtime || prev.backend !== this.currentEngine.backend || prev.format !== this.currentEngine.format || (prev.device ?? "") !== (this.currentEngine.device ?? "")) && this.engineFactory) {
|
|
4699
4698
|
this.log.info("engine selection changed — rebuilding pool in place", { meta: {
|
|
4700
4699
|
from: `${prev.backend}/${prev.device ?? "default"}`,
|
|
@@ -4796,17 +4795,18 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4796
4795
|
}, { ...state }));
|
|
4797
4796
|
}
|
|
4798
4797
|
/**
|
|
4799
|
-
* Fetch
|
|
4800
|
-
*
|
|
4801
|
-
* callers fall back to the registry's safe minimum. The
|
|
4802
|
-
* from hardware ONLY — install state
|
|
4798
|
+
* Fetch this node's inference HARDWARE (gpu/npu) for engine + device gating,
|
|
4799
|
+
* from the local kernel resolver. Returns null when the resolver is not wired
|
|
4800
|
+
* yet (cold-start), so callers fall back to the registry's safe minimum. The
|
|
4801
|
+
* engine OFFER derives from hardware ONLY — install state never gates it.
|
|
4803
4802
|
*/
|
|
4804
4803
|
/**
|
|
4805
|
-
* The local Moleculer node id (child-suffix stripped).
|
|
4806
|
-
*
|
|
4807
|
-
*
|
|
4808
|
-
*
|
|
4809
|
-
*
|
|
4804
|
+
* The local Moleculer node id (child-suffix stripped). Used to scope this
|
|
4805
|
+
* node's engine-cascade store keys (`<key>@<node>`). Hardware itself is now
|
|
4806
|
+
* resolved in-process via `ctx.kernel.inferenceEngine` (never the
|
|
4807
|
+
* `platform-probe` singleton, whose no-nodeId query resolved to the HUB and
|
|
4808
|
+
* pinned a device a remote agent couldn't run) — so this id is a store-scoping
|
|
4809
|
+
* concern, not a probe-routing one.
|
|
4810
4810
|
*/
|
|
4811
4811
|
localProbeNodeId() {
|
|
4812
4812
|
const raw = this.addonCtx?.kernel?.localNodeId ?? "hub";
|
|
@@ -4814,9 +4814,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4814
4814
|
}
|
|
4815
4815
|
async fetchProbeGatingData() {
|
|
4816
4816
|
try {
|
|
4817
|
-
|
|
4818
|
-
if (!api) return { hardware: null };
|
|
4819
|
-
return { hardware: (await api.platformProbe.getCapabilities.query({ nodeId: this.localProbeNodeId() }))?.hardware ?? null };
|
|
4817
|
+
return { hardware: await this.addonCtx?.kernel?.inferenceEngine?.resolveHardware() ?? null };
|
|
4820
4818
|
} catch {
|
|
4821
4819
|
return { hardware: null };
|
|
4822
4820
|
}
|
|
@@ -6202,15 +6200,20 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6202
6200
|
* Phase 2b — resolve the engine from the addon's new schema-backed
|
|
6203
6201
|
* fields (`engineRuntime`, `engineBackend`, `engineDevice`). Fallback
|
|
6204
6202
|
* to the legacy `KEY_ENGINE` JSON blob for pre-migration stores.
|
|
6205
|
-
*
|
|
6206
|
-
*
|
|
6203
|
+
*
|
|
6204
|
+
* The `'auto'` sentinel is treated as NO override (returns null) so the
|
|
6205
|
+
* caller re-resolves LIVE via `resolveAutoEngine()` — `'auto'` is the
|
|
6206
|
+
* self-healing default, never a persisted concrete backend. An explicit
|
|
6207
|
+
* concrete backend (onnx/openvino/coreml) is honored as an operator override.
|
|
6208
|
+
* Returns null when neither source has a concrete selection; the caller keeps
|
|
6209
|
+
* the onnx floor set at construction until `resolveAutoEngine()` runs.
|
|
6207
6210
|
*/
|
|
6208
6211
|
async loadEngine() {
|
|
6209
6212
|
const store = await this.readStore();
|
|
6210
6213
|
const storedRuntime = store["engineRuntime"];
|
|
6211
6214
|
const node = this.localProbeNodeId();
|
|
6212
6215
|
const storedBackend = readNodeEngineValue(store, "engineBackend", node);
|
|
6213
|
-
if (typeof storedBackend === "string" && storedBackend.length > 0) {
|
|
6216
|
+
if (typeof storedBackend === "string" && storedBackend.length > 0 && storedBackend !== "auto") {
|
|
6214
6217
|
const backend = storedBackend;
|
|
6215
6218
|
const storedDeviceRaw = readNodeEngineValue(store, "engineDevice", node);
|
|
6216
6219
|
const storedDevice = typeof storedDeviceRaw === "string" ? storedDeviceRaw : "";
|
|
@@ -6364,12 +6367,11 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6364
6367
|
return { success: true };
|
|
6365
6368
|
}
|
|
6366
6369
|
async reprobeEngine() {
|
|
6367
|
-
const api = this.addonCtx?.api;
|
|
6368
6370
|
let hardware = null;
|
|
6369
|
-
|
|
6370
|
-
hardware =
|
|
6371
|
+
try {
|
|
6372
|
+
hardware = await this.addonCtx?.kernel?.inferenceEngine?.resolveHardware() ?? null;
|
|
6371
6373
|
} catch {}
|
|
6372
|
-
const pick = pickBestRuntime(runtimeEnvFromProcess(toProbedHardware(hardware)), null);
|
|
6374
|
+
const pick = pickBestRuntime(runtimeEnvFromProcess(hardware ? toProbedHardware(hardware) : null), null);
|
|
6373
6375
|
const best = {
|
|
6374
6376
|
runtime: "python",
|
|
6375
6377
|
backend: pick.runtimeId,
|
|
@@ -6379,17 +6381,13 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6379
6381
|
const probedLabel = `${best.backend}/${best.device ?? "default"}`;
|
|
6380
6382
|
const rpNode = this.localProbeNodeId();
|
|
6381
6383
|
if (pick.runtimeId !== "onnx" || hardware !== null) {
|
|
6382
|
-
await this.writeStore({
|
|
6383
|
-
|
|
6384
|
-
[nodeEngineKey("engineBackend", rpNode)]: best.backend,
|
|
6385
|
-
[nodeEngineKey("engineDevice", rpNode)]: best.device ?? "cpu"
|
|
6386
|
-
});
|
|
6387
|
-
this.log.info("Re-probed engine (platform-deterministic) — wrote back", { meta: {
|
|
6384
|
+
await this.writeStore({ [nodeEngineKey("probedBestEngine", rpNode)]: probedLabel });
|
|
6385
|
+
this.log.info("Re-probed engine (local kernel) — updated probedBestEngine hint", { meta: {
|
|
6388
6386
|
backend: best.backend,
|
|
6389
6387
|
device: best.device ?? null,
|
|
6390
6388
|
probedBestEngine: probedLabel
|
|
6391
6389
|
} });
|
|
6392
|
-
} else this.log.info("Re-probe: onnx floor pending gpu probe — NOT
|
|
6390
|
+
} else this.log.info("Re-probe: onnx floor pending gpu probe — hint NOT persisted", { meta: {
|
|
6393
6391
|
backend: best.backend,
|
|
6394
6392
|
device: best.device ?? null
|
|
6395
6393
|
} });
|
|
@@ -6806,7 +6804,7 @@ var DEFAULT_CONFIG = {
|
|
|
6806
6804
|
intraOpThreads: 0,
|
|
6807
6805
|
numWorkers: 0,
|
|
6808
6806
|
engineRuntime: "python",
|
|
6809
|
-
engineBackend: "
|
|
6807
|
+
engineBackend: "auto",
|
|
6810
6808
|
engineDevice: "cpu",
|
|
6811
6809
|
probedBestEngine: "",
|
|
6812
6810
|
activeEngine: ""
|
|
@@ -6859,7 +6857,7 @@ var POOL_BOUND_KEYS = [
|
|
|
6859
6857
|
"intraOpThreads",
|
|
6860
6858
|
"numWorkers"
|
|
6861
6859
|
];
|
|
6862
|
-
var DetectionPipelineAddon = class extends BaseAddon {
|
|
6860
|
+
var DetectionPipelineAddon = class DetectionPipelineAddon extends BaseAddon {
|
|
6863
6861
|
provider = null;
|
|
6864
6862
|
/** Last non-null probed hardware PER NODE — reused when the probe transiently
|
|
6865
6863
|
* returns null so offered backends / device lists don't collapse. Keyed by
|
|
@@ -6934,7 +6932,10 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
6934
6932
|
type: "select",
|
|
6935
6933
|
key: "engineBackend",
|
|
6936
6934
|
label: "Execution provider",
|
|
6937
|
-
options: [
|
|
6935
|
+
options: [{
|
|
6936
|
+
value: "auto",
|
|
6937
|
+
label: "Auto (best for this node)"
|
|
6938
|
+
}, ...STATIC_BACKEND_OPTIONS],
|
|
6938
6939
|
default: DEFAULT_CONFIG.engineBackend,
|
|
6939
6940
|
immediate: true,
|
|
6940
6941
|
perNode: true
|
|
@@ -7075,12 +7076,17 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7075
7076
|
const env = await this.probeHardwareEnv(targetNode);
|
|
7076
7077
|
const hardware = env.hardware;
|
|
7077
7078
|
const offered = supportedRuntimes(env);
|
|
7078
|
-
const runtimeBackends =
|
|
7079
|
+
const runtimeBackends = [{
|
|
7080
|
+
value: "auto",
|
|
7081
|
+
label: "Auto (best for this node)"
|
|
7082
|
+
}, ...offered.map((id) => ({
|
|
7079
7083
|
value: id,
|
|
7080
7084
|
label: runtimeLabel(id)
|
|
7081
|
-
}));
|
|
7085
|
+
}))];
|
|
7082
7086
|
const storedBackend = typeof merged.engineBackend === "string" ? merged.engineBackend : "";
|
|
7087
|
+
const isAuto = storedBackend === "auto";
|
|
7083
7088
|
const backend = (() => {
|
|
7089
|
+
if (isAuto) return pickBestRuntime(env, null).runtimeId;
|
|
7084
7090
|
const rid = toRuntimeId(storedBackend);
|
|
7085
7091
|
if (rid === "onnx") return "onnx";
|
|
7086
7092
|
if (offered.includes(rid)) return rid;
|
|
@@ -7091,9 +7097,10 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7091
7097
|
const device = deviceOptions.find((d) => d.value === storedDevice)?.value ?? defaultDeviceFor(backend);
|
|
7092
7098
|
const prov = targetNode === this.localNodeId() ? this.provider?.getEngineProvisioning() : void 0;
|
|
7093
7099
|
const activeEngine = prov && prov.runtimeId ? `${prov.runtimeId}/${prov.device ?? "default"} (${prov.state})` : "";
|
|
7100
|
+
const displayBackend = isAuto ? "auto" : backend;
|
|
7094
7101
|
const raw = {
|
|
7095
7102
|
...merged,
|
|
7096
|
-
engineBackend:
|
|
7103
|
+
engineBackend: displayBackend,
|
|
7097
7104
|
engineDevice: device,
|
|
7098
7105
|
activeEngine
|
|
7099
7106
|
};
|
|
@@ -7211,7 +7218,7 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7211
7218
|
const api = this.ctxIfReady?.api;
|
|
7212
7219
|
if (!api) return null;
|
|
7213
7220
|
const node = nodeId ?? this.localNodeId();
|
|
7214
|
-
const hw = (node === this.localNodeId() ? await api.platformProbe.getCapabilities.query() : await api.platformProbe.getCapabilities.query(
|
|
7221
|
+
const hw = (node === this.localNodeId() ? await api.platformProbe.getCapabilities.query() : await api.platformProbe.getCapabilities.query({ nodeId: node }))?.hardware;
|
|
7215
7222
|
if (!hw) return null;
|
|
7216
7223
|
return {
|
|
7217
7224
|
npu: hw.npu ? { type: hw.npu.type } : null,
|
|
@@ -7249,7 +7256,7 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7249
7256
|
* a reason to disagree.
|
|
7250
7257
|
*/
|
|
7251
7258
|
resolveBackendTuning() {
|
|
7252
|
-
const t = tuningFor(toRuntimeId(this.config.engineBackend));
|
|
7259
|
+
const t = tuningFor(this.config.engineBackend === "auto" ? this.provider?.resolvedEngineBackend() ?? "onnx" : toRuntimeId(this.config.engineBackend));
|
|
7253
7260
|
const num = (v, dflt) => typeof v === "number" && v > 0 ? v : dflt;
|
|
7254
7261
|
const batch = (v, dflt) => v === "none" || v === "list" || v === "window" ? v : dflt;
|
|
7255
7262
|
return {
|
|
@@ -7262,6 +7269,34 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7262
7269
|
numWorkers: num(t["numWorkers"], 1)
|
|
7263
7270
|
};
|
|
7264
7271
|
}
|
|
7272
|
+
/**
|
|
7273
|
+
* Construct a fresh provider with the given effective tuning. Single source of
|
|
7274
|
+
* truth for the provider wiring — shared by `onInitialize`, the post-resolve
|
|
7275
|
+
* tuning reconciliation, and the `onConfigChanged` pool respawn.
|
|
7276
|
+
*/
|
|
7277
|
+
buildProvider(modelsDir, tuning) {
|
|
7278
|
+
if (!this.ctx.settings) throw new Error("DetectionPipelineAddon: ctx.settings not available");
|
|
7279
|
+
return new DetectionPipelineProvider(this.ctx.settings, modelsDir, this.ctx.logger, this.ctx.eventBus ?? null, () => ({ sections: [] }), {
|
|
7280
|
+
concurrency: tuning.concurrency,
|
|
7281
|
+
tuning: {
|
|
7282
|
+
batchMode: tuning.batchMode,
|
|
7283
|
+
windowMs: tuning.windowMs,
|
|
7284
|
+
maxBatchSize: tuning.maxBatchSize,
|
|
7285
|
+
numStreams: tuning.numStreams,
|
|
7286
|
+
intraOpThreads: tuning.intraOpThreads
|
|
7287
|
+
},
|
|
7288
|
+
numWorkers: tuning.numWorkers,
|
|
7289
|
+
pythonPath: this.pythonPath,
|
|
7290
|
+
pythonAddonDir: this.pythonAddonDir
|
|
7291
|
+
});
|
|
7292
|
+
}
|
|
7293
|
+
/**
|
|
7294
|
+
* Pool-bound tuning keys of `a` and `b` are equal (used to decide whether a
|
|
7295
|
+
* post-resolve / config-change respawn is actually needed).
|
|
7296
|
+
*/
|
|
7297
|
+
static poolTuningEqual(a, b) {
|
|
7298
|
+
return a.concurrency === b.concurrency && a.batchMode === b.batchMode && a.windowMs === b.windowMs && a.maxBatchSize === b.maxBatchSize && a.numStreams === b.numStreams && a.intraOpThreads === b.intraOpThreads && a.numWorkers === b.numWorkers;
|
|
7299
|
+
}
|
|
7265
7300
|
async onInitialize() {
|
|
7266
7301
|
const modelsDir = await this.resolveModelsDir();
|
|
7267
7302
|
if (!this.ctx.settings) throw new Error("DetectionPipelineAddon: ctx.settings not available");
|
|
@@ -7270,22 +7305,20 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7270
7305
|
if (py.ok && py.pythonPath) this.pythonPath = py.pythonPath;
|
|
7271
7306
|
else this.ctx.logger.warn("Detection engine boot continues without Python — selection will provision on demand", {});
|
|
7272
7307
|
await this.proactivelyInstallOpenvino();
|
|
7273
|
-
const
|
|
7274
|
-
this.provider =
|
|
7275
|
-
concurrency: effectiveTuning.concurrency,
|
|
7276
|
-
tuning: {
|
|
7277
|
-
batchMode: effectiveTuning.batchMode,
|
|
7278
|
-
windowMs: effectiveTuning.windowMs,
|
|
7279
|
-
maxBatchSize: effectiveTuning.maxBatchSize,
|
|
7280
|
-
numStreams: effectiveTuning.numStreams,
|
|
7281
|
-
intraOpThreads: effectiveTuning.intraOpThreads
|
|
7282
|
-
},
|
|
7283
|
-
numWorkers: effectiveTuning.numWorkers,
|
|
7284
|
-
pythonPath: this.pythonPath,
|
|
7285
|
-
pythonAddonDir: this.pythonAddonDir
|
|
7286
|
-
});
|
|
7308
|
+
const initialTuning = this.resolveBackendTuning();
|
|
7309
|
+
this.provider = this.buildProvider(modelsDir, initialTuning);
|
|
7287
7310
|
await this.provider.init();
|
|
7288
7311
|
await this.provider.setApi(this.ctx);
|
|
7312
|
+
const resolvedTuning = this.resolveBackendTuning();
|
|
7313
|
+
if (!DetectionPipelineAddon.poolTuningEqual(initialTuning, resolvedTuning)) {
|
|
7314
|
+
this.ctx.logger.info("detection-pipeline tuning reconciled to resolved engine", { meta: {
|
|
7315
|
+
from: initialTuning,
|
|
7316
|
+
to: resolvedTuning
|
|
7317
|
+
} });
|
|
7318
|
+
this.provider = this.buildProvider(modelsDir, resolvedTuning);
|
|
7319
|
+
await this.provider.init();
|
|
7320
|
+
await this.provider.setApi(this.ctx);
|
|
7321
|
+
}
|
|
7289
7322
|
if (!this.config.probedBestEngine) await this.provider.reprobeEngine().catch((err) => {
|
|
7290
7323
|
this.ctx.logger.warn("auto-reprobe engine failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
7291
7324
|
});
|
|
@@ -7342,13 +7375,18 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7342
7375
|
* first loaded (gated by `loadEngine`'s `isPythonBackendAvailable` check).
|
|
7343
7376
|
*
|
|
7344
7377
|
* Failure is non-fatal: a warning is logged and the addon continues with
|
|
7345
|
-
* the onnx-cpu baseline. The hardware
|
|
7346
|
-
* if the
|
|
7378
|
+
* the onnx-cpu baseline. The hardware resolve itself is also best-effort —
|
|
7379
|
+
* if the kernel resolver isn't wired yet the error is caught here.
|
|
7347
7380
|
*/
|
|
7348
7381
|
async proactivelyInstallOpenvino() {
|
|
7349
7382
|
if (!this.pythonAddonDir || !this.pythonPath) return;
|
|
7350
7383
|
try {
|
|
7351
|
-
const
|
|
7384
|
+
const hw = await this.ctx.kernel?.inferenceEngine?.resolveHardware();
|
|
7385
|
+
const hardware = {
|
|
7386
|
+
platform: process.platform,
|
|
7387
|
+
gpu: hw?.gpu ?? null,
|
|
7388
|
+
npu: hw?.npu ?? null
|
|
7389
|
+
};
|
|
7352
7390
|
if (!shouldInstallOpenvino(hardware)) return;
|
|
7353
7391
|
this.ctx.logger.info("Intel hardware detected — proactively installing OpenVINO Python package", { meta: {
|
|
7354
7392
|
gpu: hardware.gpu?.type ?? null,
|
|
@@ -7427,21 +7465,7 @@ var DetectionPipelineAddon = class extends BaseAddon {
|
|
|
7427
7465
|
this.ctx.logger.warn("provider shutdown failed during tuning respawn", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
7428
7466
|
}
|
|
7429
7467
|
const modelsDir = await this.resolveModelsDir();
|
|
7430
|
-
|
|
7431
|
-
const effectiveTuning = this.resolveBackendTuning();
|
|
7432
|
-
this.provider = new DetectionPipelineProvider(this.ctx.settings, modelsDir, this.ctx.logger, this.ctx.eventBus ?? null, () => ({ sections: [] }), {
|
|
7433
|
-
concurrency: effectiveTuning.concurrency,
|
|
7434
|
-
tuning: {
|
|
7435
|
-
batchMode: effectiveTuning.batchMode,
|
|
7436
|
-
windowMs: effectiveTuning.windowMs,
|
|
7437
|
-
maxBatchSize: effectiveTuning.maxBatchSize,
|
|
7438
|
-
numStreams: effectiveTuning.numStreams,
|
|
7439
|
-
intraOpThreads: effectiveTuning.intraOpThreads
|
|
7440
|
-
},
|
|
7441
|
-
numWorkers: effectiveTuning.numWorkers,
|
|
7442
|
-
pythonPath: this.pythonPath,
|
|
7443
|
-
pythonAddonDir: this.pythonAddonDir
|
|
7444
|
-
});
|
|
7468
|
+
this.provider = this.buildProvider(modelsDir, this.resolveBackendTuning());
|
|
7445
7469
|
await this.provider.init();
|
|
7446
7470
|
await this.provider.setApi(this.ctx);
|
|
7447
7471
|
await this.provider.warmPool();
|
|
@@ -16403,7 +16403,10 @@ var AgentLoadSummarySchema = object({
|
|
|
16403
16403
|
online: boolean(),
|
|
16404
16404
|
load: RunnerLocalLoadSchema,
|
|
16405
16405
|
/** Computed score used by the L2 capacity balancer (lower = less loaded). */
|
|
16406
|
-
score: number()
|
|
16406
|
+
score: number(),
|
|
16407
|
+
/** This node's decode hwaccel backend (per-node `probedBestHwaccel`), or null
|
|
16408
|
+
* when not yet probed — for the cluster Pipeline table UI (P0.2). */
|
|
16409
|
+
decodeHwaccel: string().nullable()
|
|
16407
16410
|
});
|
|
16408
16411
|
/**
|
|
16409
16412
|
* Aggregate metrics across the whole detection cluster. Replaces the legacy
|
|
@@ -19034,7 +19037,7 @@ var HardwareEncoderIdSchema = _enum([
|
|
|
19034
19037
|
"libx264",
|
|
19035
19038
|
"libx265"
|
|
19036
19039
|
]);
|
|
19037
|
-
|
|
19040
|
+
object({
|
|
19038
19041
|
encoders: array(object({
|
|
19039
19042
|
encoder: HardwareEncoderIdSchema,
|
|
19040
19043
|
codec: _enum(["H264", "H265"]),
|
|
@@ -19053,15 +19056,7 @@ var HardwareEncodersSchema = object({
|
|
|
19053
19056
|
defaultH265: HardwareEncoderIdSchema,
|
|
19054
19057
|
probedAt: number()
|
|
19055
19058
|
});
|
|
19056
|
-
|
|
19057
|
-
* Decode-side companion to {@link HardwareEncodersSchema}: the `-hwaccel`
|
|
19058
|
-
* methods the configured ffmpeg binary actually supports (parsed from
|
|
19059
|
-
* `ffmpeg -hwaccels`). Used to gate decode-hwaccel attempts so the transcode
|
|
19060
|
-
* egress never spends a spawn on a backend this build cannot offer. Per-stream
|
|
19061
|
-
* decode fragility (e.g. VideoToolbox HEVC) is still handled by the egress's
|
|
19062
|
-
* software fallback — this only filters out wholly-unsupported backends.
|
|
19063
|
-
*/
|
|
19064
|
-
var HardwareDecodeAccelsSchema = object({
|
|
19059
|
+
object({
|
|
19065
19060
|
methods: array(string()).readonly(),
|
|
19066
19061
|
probedAt: number()
|
|
19067
19062
|
});
|
|
@@ -19124,13 +19119,7 @@ var ResolvedInferenceConfigSchema = object({
|
|
|
19124
19119
|
format: ModelFormatSchema,
|
|
19125
19120
|
reason: string()
|
|
19126
19121
|
});
|
|
19127
|
-
method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema), method(object({ requirements: array(ModelRequirementSchema).readonly() }), ResolvedInferenceConfigSchema), method(object({ prefer: HwAccelBackendInputSchema }), HwAccelResolutionSchema)
|
|
19128
|
-
kind: "mutation",
|
|
19129
|
-
auth: "admin"
|
|
19130
|
-
}), method(_void(), HardwareDecodeAccelsSchema), method(_void(), HardwareDecodeAccelsSchema, {
|
|
19131
|
-
kind: "mutation",
|
|
19132
|
-
auth: "admin"
|
|
19133
|
-
});
|
|
19122
|
+
method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema), method(object({ requirements: array(ModelRequirementSchema).readonly() }), ResolvedInferenceConfigSchema), method(object({ prefer: HwAccelBackendInputSchema }), HwAccelResolutionSchema);
|
|
19134
19123
|
var PtzPresetSchema = object({
|
|
19135
19124
|
id: string(),
|
|
19136
19125
|
name: string()
|
|
@@ -22788,30 +22777,6 @@ Object.freeze({
|
|
|
22788
22777
|
addonId: null,
|
|
22789
22778
|
access: "view"
|
|
22790
22779
|
},
|
|
22791
|
-
"platformProbe.getHardwareDecodeAccels": {
|
|
22792
|
-
capName: "platform-probe",
|
|
22793
|
-
capScope: "system",
|
|
22794
|
-
addonId: null,
|
|
22795
|
-
access: "view"
|
|
22796
|
-
},
|
|
22797
|
-
"platformProbe.getHardwareEncoders": {
|
|
22798
|
-
capName: "platform-probe",
|
|
22799
|
-
capScope: "system",
|
|
22800
|
-
addonId: null,
|
|
22801
|
-
access: "view"
|
|
22802
|
-
},
|
|
22803
|
-
"platformProbe.refreshHardwareDecodeAccels": {
|
|
22804
|
-
capName: "platform-probe",
|
|
22805
|
-
capScope: "system",
|
|
22806
|
-
addonId: null,
|
|
22807
|
-
access: "create"
|
|
22808
|
-
},
|
|
22809
|
-
"platformProbe.refreshHardwareEncoders": {
|
|
22810
|
-
capName: "platform-probe",
|
|
22811
|
-
capScope: "system",
|
|
22812
|
-
addonId: null,
|
|
22813
|
-
access: "create"
|
|
22814
|
-
},
|
|
22815
22780
|
"platformProbe.resolveHwAccel": {
|
|
22816
22781
|
capName: "platform-probe",
|
|
22817
22782
|
capScope: "system",
|