@camstack/addon-pipeline 1.2.70 → 1.2.71
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/detection-pipeline/index.js +2 -2
- package/dist/detection-pipeline/index.mjs +2 -2
- package/dist/{dist-cR-pvD_z.js → dist-CtOVWTCi.js} +78 -33
- package/dist/{dist-BPaa4_z6.mjs → dist-D1Xk5Tji.mjs} +78 -33
- package/dist/{event-loop-stall-monitor-STRdnQWm.js → event-loop-stall-monitor-BJs7Yws7.js} +1 -1
- package/dist/{event-loop-stall-monitor-B79REtL2.mjs → event-loop-stall-monitor-Cmbt664E.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 +95 -28
- package/dist/pipeline-runner/index.mjs +95 -28
- package/dist/recorder/index.js +365 -73
- package/dist/recorder/index.mjs +365 -73
- package/dist/session-decode/decode-worker-child.js +483 -52
- package/dist/session-decode/decode-worker-child.mjs +483 -52
- package/dist/stream-broker/_stub.js +660 -556
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B-HGBNad.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BWf4H4Nl.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cu_kQpIy.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CExO0piw.mjs +26 -0
- package/dist/stream-broker/{hostInit-B12DHOv7.mjs → hostInit-DD5Z1U6p.mjs} +3 -3
- package/dist/stream-broker/index.js +1 -1
- package/dist/stream-broker/index.mjs +1 -1
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-C7V1qIIA.js → worker-protocol-DEV7g32b.js} +26 -19
- package/dist/{worker-protocol-CBO8nwQj.mjs → worker-protocol-Dm6LQ9Ls.mjs} +26 -19
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D1CqbPrT.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-NjvjJWz-.mjs +0 -26
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { At as string, Ct as boolean, Dt as number, Et as literal, K as pipelineRunnerCapability, M as deriveDetailCropRect, Mt as EventCategory, Ot as object, St as array, Tt as lazy, U as pickDetailCropConvention, W as pickNativeLeaseOverride, dt as createEvent, gt as nodePin, j as defineCustomActions, k as customAction, s as DEFAULT_DETAIL_CROP_CONVENTION, st as BaseAddon, tt as errMsg, u as DEVICE_BACKEND_TO_FORMAT, xt as _enum } from "../dist-
|
|
2
|
-
import { c as getStepDefinition, t as attributeStall } from "../event-loop-stall-monitor-
|
|
3
|
-
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-
|
|
1
|
+
import { At as string, Ct as boolean, Dt as number, Et as literal, K as pipelineRunnerCapability, M as deriveDetailCropRect, Mt as EventCategory, Ot as object, St as array, Tt as lazy, U as pickDetailCropConvention, W as pickNativeLeaseOverride, dt as createEvent, gt as nodePin, j as defineCustomActions, k as customAction, s as DEFAULT_DETAIL_CROP_CONVENTION, st as BaseAddon, tt as errMsg, u as DEVICE_BACKEND_TO_FORMAT, xt as _enum } from "../dist-D1Xk5Tji.mjs";
|
|
2
|
+
import { c as getStepDefinition, t as attributeStall } from "../event-loop-stall-monitor-Cmbt664E.mjs";
|
|
3
|
+
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-Dm6LQ9Ls.mjs";
|
|
4
4
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-B-mb8uWx.mjs";
|
|
6
6
|
import { i as withDetectionIntent, n as profileForStreamId, t as isRemoteRestream } from "../remote-restream-Ci7RXNGb.mjs";
|
|
@@ -10,28 +10,6 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
import { PerformanceObserver } from "node:perf_hooks";
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
//#region src/session-decode/fork-decode-worker.ts
|
|
13
|
-
/**
|
|
14
|
-
* Real `fork` implementation for the session-decode coordinator — Epic C P1,
|
|
15
|
-
* Task 4.
|
|
16
|
-
*
|
|
17
|
-
* Spawns the decode-worker child (`decode-worker-child.ts`, Task 2) as a
|
|
18
|
-
* dedicated `child_process.fork` and adapts the returned `ChildProcess` to the
|
|
19
|
-
* coordinator's minimal {@link ForkedChildLike} contract WITHOUT any cast —
|
|
20
|
-
* an explicit forwarding wrapper, so a wider Node `ChildProcess` signature
|
|
21
|
-
* never has to structurally satisfy the narrower interface.
|
|
22
|
-
*
|
|
23
|
-
* `serialization: 'advanced'` is MANDATORY: Node's default 'json' IPC
|
|
24
|
-
* base64-serialises the `buffer` reply's `Uint8Array`, breaking the "raw
|
|
25
|
-
* bytes, not base64" contract the coordinator + `worker-protocol.ts`'s
|
|
26
|
-
* `value.bytes instanceof Uint8Array` guard both depend on. Advanced (V8
|
|
27
|
-
* structured-clone) preserves the typed array on the wire.
|
|
28
|
-
*
|
|
29
|
-
* The child entry is resolved relative to THIS module's built location. Both
|
|
30
|
-
* this module and `pipeline-runner/index.ts` bundle into the SAME entry
|
|
31
|
-
* (`dist/pipeline-runner/index.js`, `manualChunks: () => null`), so
|
|
32
|
-
* `import.meta.url` here is that file's URL and the sibling child lands at
|
|
33
|
-
* `dist/session-decode/decode-worker-child.js` (its own vite build entry).
|
|
34
|
-
*/
|
|
35
13
|
/** Absolute path to the built decode-worker child entry (a vite build entry). */
|
|
36
14
|
var CHILD_ENTRY_PATH = fileURLToPath(new URL("../session-decode/decode-worker-child.js", import.meta.url));
|
|
37
15
|
/**
|
|
@@ -689,8 +667,24 @@ var SessionDecodeSession = class {
|
|
|
689
667
|
});
|
|
690
668
|
}
|
|
691
669
|
/**
|
|
692
|
-
*
|
|
693
|
-
*
|
|
670
|
+
* The runner has this frame's detections: cut one native subject tile per box
|
|
671
|
+
* and END the hold on `frameId`. Fire and forget (no reply) so the encode can
|
|
672
|
+
* never delay the runner; a dropped message costs only the tiles.
|
|
673
|
+
*
|
|
674
|
+
* An EMPTY box list is still sent — it is how a frame that detected nothing
|
|
675
|
+
* releases its hold, and that is the common case.
|
|
676
|
+
*/
|
|
677
|
+
cutTiles(frameId, bboxes) {
|
|
678
|
+
if (this.exited) return;
|
|
679
|
+
this.trySend({
|
|
680
|
+
kind: "cutTiles",
|
|
681
|
+
frameId,
|
|
682
|
+
bboxes
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Prompt-release the worker's RAM native-frame hold for `frameId`. Fire and
|
|
687
|
+
* forget (no reply): the hold is also bounded by a frame count, so a dropped
|
|
694
688
|
* release only defers reclaim. No-op once the worker has exited.
|
|
695
689
|
*/
|
|
696
690
|
releaseLease(frameId) {
|
|
@@ -970,6 +964,7 @@ function buildFrameImage(session, reply) {
|
|
|
970
964
|
return session.requestBuffer(reply.frameId, opts);
|
|
971
965
|
},
|
|
972
966
|
nativeCrop: (bbox, maxWidth) => session.requestNativeCrop(reply.frameId, bbox, maxWidth),
|
|
967
|
+
cutTiles: (bboxes) => session.cutTiles(reply.frameId, bboxes),
|
|
973
968
|
releaseNativeLease: () => session.releaseLease(reply.frameId),
|
|
974
969
|
markInferred: () => session.markInferred(reply.frameId),
|
|
975
970
|
close: () => {
|
|
@@ -1110,6 +1105,7 @@ function startSessionDecodePump(deps) {
|
|
|
1110
1105
|
const image = frame.image;
|
|
1111
1106
|
const cropFn = image.nativeCrop;
|
|
1112
1107
|
const nativeCrop = cropFn ? Object.assign((bbox, maxWidth) => cropFn(bbox, maxWidth), {
|
|
1108
|
+
cutTiles: (bboxes) => image.cutTiles?.(bboxes),
|
|
1113
1109
|
release: () => image.releaseNativeLease?.(),
|
|
1114
1110
|
markInferred: () => image.markInferred?.()
|
|
1115
1111
|
}) : void 0;
|
|
@@ -2517,7 +2513,7 @@ var NATIVE_LEASE_OWNER_ADDON_ID = "pipeline-orchestrator";
|
|
|
2517
2513
|
* old value.
|
|
2518
2514
|
*/
|
|
2519
2515
|
function sameOverride(a, b) {
|
|
2520
|
-
return a.
|
|
2516
|
+
return a.holdFrames === b.holdFrames && a.budgetMb === b.budgetMb && a.activityMs === b.activityMs && a.admission === b.admission && a.tileBudgetMb === b.tileBudgetMb;
|
|
2521
2517
|
}
|
|
2522
2518
|
/**
|
|
2523
2519
|
* TTL-cached read of the cluster native-lease knobs.
|
|
@@ -3794,6 +3790,42 @@ async function runStatelessStep(deps, input) {
|
|
|
3794
3790
|
details
|
|
3795
3791
|
};
|
|
3796
3792
|
}
|
|
3793
|
+
/**
|
|
3794
|
+
* Normalised boxes for the subjects worth a tile, highest confidence first,
|
|
3795
|
+
* capped.
|
|
3796
|
+
*
|
|
3797
|
+
* Returns an empty array for a frame with no usable detections — and the caller
|
|
3798
|
+
* still sends it: an empty `cutTiles` is how a frame that detected nothing ends
|
|
3799
|
+
* its hold, which is the majority of frames and the whole reason this design
|
|
3800
|
+
* costs less than the one it replaces.
|
|
3801
|
+
*
|
|
3802
|
+
* A degenerate or non-finite box is DROPPED rather than clamped: a zero-area
|
|
3803
|
+
* container serves nothing, and a NaN one would poison the worker's geometry.
|
|
3804
|
+
*/
|
|
3805
|
+
function planTileCuts(detections, frame, maxSubjects = 4) {
|
|
3806
|
+
if (frame.width <= 0 || frame.height <= 0) return [];
|
|
3807
|
+
const ordered = [...detections.filter((d) => isUsable(d.bbox))].sort((a, b) => b.score - a.score);
|
|
3808
|
+
const out = [];
|
|
3809
|
+
for (const detection of ordered.slice(0, Math.max(0, maxSubjects))) {
|
|
3810
|
+
const { x, y, width, height } = detection.bbox;
|
|
3811
|
+
out.push({
|
|
3812
|
+
x: x / frame.width,
|
|
3813
|
+
y: y / frame.height,
|
|
3814
|
+
w: width / frame.width,
|
|
3815
|
+
h: height / frame.height
|
|
3816
|
+
});
|
|
3817
|
+
}
|
|
3818
|
+
return out;
|
|
3819
|
+
}
|
|
3820
|
+
function isUsable(bbox) {
|
|
3821
|
+
if (![
|
|
3822
|
+
bbox.x,
|
|
3823
|
+
bbox.y,
|
|
3824
|
+
bbox.width,
|
|
3825
|
+
bbox.height
|
|
3826
|
+
].every((v) => Number.isFinite(v))) return false;
|
|
3827
|
+
return bbox.width > 0 && bbox.height > 0;
|
|
3828
|
+
}
|
|
3797
3829
|
//#endregion
|
|
3798
3830
|
//#region src/pipeline-runner/index.ts
|
|
3799
3831
|
var DEFAULT_CONFIG = {
|
|
@@ -4282,6 +4314,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
4282
4314
|
this.handleDetectionStreamChange(deviceId, action);
|
|
4283
4315
|
});
|
|
4284
4316
|
this.runner.onResult(async (deviceId, frame, result, _streamType, handle) => {
|
|
4317
|
+
this.cutSubjectTiles(deviceId, result, handle);
|
|
4285
4318
|
this.emitInferenceResult(deviceId, frame, result, handle);
|
|
4286
4319
|
const detectionCount = result.detections?.length ?? 0;
|
|
4287
4320
|
this.runner?.noteDetectionResult(deviceId, detectionCount);
|
|
@@ -5103,6 +5136,40 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
5103
5136
|
}, resolved.tier, input.encodeJpeg);
|
|
5104
5137
|
}
|
|
5105
5138
|
/**
|
|
5139
|
+
* Turn a finished frame into subject TILES and end its hold — the runner half
|
|
5140
|
+
* of R2 (`docs/design/2026-08-13-native-lease-two-tier-redesign.md`).
|
|
5141
|
+
*
|
|
5142
|
+
* Called from the result callback, which is the last instant at which the
|
|
5143
|
+
* frame's native pixels exist and its detections are known at the same time.
|
|
5144
|
+
* Every path through here ends the hold, including the one where there is
|
|
5145
|
+
* nothing to cut: a frame that detected nothing is the majority of frames and
|
|
5146
|
+
* releasing it promptly is most of the RAM this redesign gives back.
|
|
5147
|
+
*
|
|
5148
|
+
* Deliberately synchronous and unawaited. The worker replies to nothing, so
|
|
5149
|
+
* there is nothing to wait for, and a detection result must never be delayed
|
|
5150
|
+
* by an encode.
|
|
5151
|
+
*/
|
|
5152
|
+
cutSubjectTiles(deviceId, result, handle) {
|
|
5153
|
+
if (!handle) return;
|
|
5154
|
+
const found = this.nativeCropRegistry.get(handle);
|
|
5155
|
+
if (!found) return;
|
|
5156
|
+
const boxes = planTileCuts(result.detections ?? [], {
|
|
5157
|
+
width: result.width,
|
|
5158
|
+
height: result.height
|
|
5159
|
+
});
|
|
5160
|
+
try {
|
|
5161
|
+
found.request.cutTiles(boxes);
|
|
5162
|
+
} catch (err) {
|
|
5163
|
+
this.ctx.logger.debug("subject tile cut could not be dispatched", {
|
|
5164
|
+
tags: { deviceId },
|
|
5165
|
+
meta: {
|
|
5166
|
+
subjects: boxes.length,
|
|
5167
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5168
|
+
}
|
|
5169
|
+
});
|
|
5170
|
+
}
|
|
5171
|
+
}
|
|
5172
|
+
/**
|
|
5106
5173
|
* The native-lease half of {@link getNativeCrop}, extracted so the DETAIL path
|
|
5107
5174
|
* can keep the miss REASON the cap's `null` return has no room for. Both
|
|
5108
5175
|
* callers share this one decision — a second copy of the tier arithmetic is
|