@camstack/addon-pipeline 0.1.13 → 0.1.15
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 +2 -4
- package/dist/audio-analyzer/index.js.map +1 -1
- package/dist/audio-analyzer/index.mjs +2 -4
- package/dist/audio-analyzer/index.mjs.map +1 -1
- package/dist/audio-codec-nodeav/index.js +1 -1
- package/dist/audio-codec-nodeav/index.mjs +1 -1
- package/dist/decoder-nodeav/index.js +552 -18
- package/dist/decoder-nodeav/index.js.map +1 -1
- package/dist/decoder-nodeav/index.mjs +553 -19
- package/dist/decoder-nodeav/index.mjs.map +1 -1
- package/dist/detection-pipeline/index.js +2 -4
- package/dist/detection-pipeline/index.js.map +1 -1
- package/dist/detection-pipeline/index.mjs +2 -4
- package/dist/detection-pipeline/index.mjs.map +1 -1
- package/dist/{index-BwLnHesq.mjs → index-CVzLrojg.mjs} +567 -327
- package/dist/index-CVzLrojg.mjs.map +1 -0
- package/dist/{index-BBpVDiWL.js → index-p-6GfKOg.js} +567 -327
- package/dist/index-p-6GfKOg.js.map +1 -0
- package/dist/motion-wasm/index.js +2 -4
- package/dist/motion-wasm/index.js.map +1 -1
- package/dist/motion-wasm/index.mjs +2 -4
- package/dist/motion-wasm/index.mjs.map +1 -1
- package/dist/pipeline-runner/index.js +133 -54
- package/dist/pipeline-runner/index.js.map +1 -1
- package/dist/pipeline-runner/index.mjs +133 -54
- package/dist/pipeline-runner/index.mjs.map +1 -1
- package/dist/stream-broker/@mf-types.zip +0 -0
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-d8PmLbO2.mjs +19 -0
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-B4l8Nb2y.mjs +20 -0
- package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-DePVYdid.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-DAssX3h0.mjs} +4 -2
- package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-CBlCGyx5.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-DFoJJhpt.mjs} +1 -1
- package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-DZchZKbW.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-x7XMEeuJ.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B8d_i3jf.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CWHjxwIc.mjs} +6 -6
- package/dist/stream-broker/{client-BK73l2KT.mjs → client-CZXrddDR.mjs} +2990 -3217
- package/dist/stream-broker/{hostInit-oba_vMZE.mjs → hostInit-B86vUcFC.mjs} +12 -12
- package/dist/stream-broker/{index-COebxMhm.mjs → index-BCEx31Mh.mjs} +4032 -3582
- package/dist/stream-broker/{index-BAZcm437.mjs → index-BvV3RVTZ.mjs} +1 -1
- package/dist/stream-broker/{index-IUYKHbxX.mjs → index-C0BzaWmB.mjs} +1 -1
- package/dist/stream-broker/index-CWkKuNLr.mjs +232 -0
- package/dist/stream-broker/{index-ns1fRD30.mjs → index-CZNxa0ad.mjs} +1 -1
- package/dist/stream-broker/index-Kb4xa8FX.mjs +36403 -0
- package/dist/stream-broker/{index-BxHaCH3N.mjs → index-KtR7Pp0O.mjs} +1 -1
- package/dist/stream-broker/{index-Ss9m7Jum.mjs → index-cYW01SNH.mjs} +1 -1
- package/dist/stream-broker/index.js +805 -544
- package/dist/stream-broker/index.js.map +1 -1
- package/dist/stream-broker/index.mjs +805 -522
- package/dist/stream-broker/index.mjs.map +1 -1
- package/dist/stream-broker/{jsx-runtime-ZdY5pIZz.mjs → jsx-runtime-B_evVsXl.mjs} +1 -1
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +23 -31
- package/dist/index-BBpVDiWL.js.map +0 -1
- package/dist/index-BwLnHesq.mjs.map +0 -1
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-p-Z3JTk9.mjs +0 -19
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-MYpjp-jd.mjs +0 -20
- package/dist/stream-broker/index-BkB3U-Tc.mjs +0 -20852
- package/python/__pycache__/inference_pool.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/_safety.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-313.pyc +0 -0
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
import { o as object, s as string, _ as _enum, l as lazy, a as array, b as boolean, n as number, d as defineCustomActions, c as customAction, B as BaseAddon, E as EventCategory, p as pipelineRunnerCapability,
|
|
1
|
+
import { e as errMsg, o as object, s as string, _ as _enum, l as lazy, a as array, b as boolean, n as number, d as defineCustomActions, c as customAction, B as BaseAddon, E as EventCategory, p as pipelineRunnerCapability, f as createEvent } from "../index-CVzLrojg.mjs";
|
|
2
|
+
import { FrameRingReaderCache } from "@camstack/shm-ring";
|
|
2
3
|
class FrameQueue {
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* `clone` runs on every {@link enqueue} to detach a queue-owned copy from
|
|
6
|
+
* the (possibly borrowed) source — required by the D9 Task 7b ownership
|
|
7
|
+
* contract above. Motion call sites pass {@link ownFrame}; the detection
|
|
8
|
+
* path passes a clone that copies its inner frame's pixel buffer.
|
|
9
|
+
*/
|
|
10
|
+
constructor(maxSize, clone) {
|
|
4
11
|
this.maxSize = maxSize;
|
|
12
|
+
this.clone = clone;
|
|
5
13
|
}
|
|
6
14
|
latest = null;
|
|
7
15
|
_droppedFrames = 0;
|
|
8
|
-
|
|
16
|
+
clone;
|
|
17
|
+
enqueue(item) {
|
|
9
18
|
if (this.latest !== null) {
|
|
10
19
|
this._droppedFrames++;
|
|
11
20
|
}
|
|
12
|
-
this.latest =
|
|
21
|
+
this.latest = this.clone(item);
|
|
13
22
|
}
|
|
14
23
|
dequeue() {
|
|
15
|
-
const
|
|
24
|
+
const item = this.latest ?? void 0;
|
|
16
25
|
this.latest = null;
|
|
17
|
-
return
|
|
26
|
+
return item;
|
|
18
27
|
}
|
|
19
28
|
get size() {
|
|
20
29
|
return this.latest !== null ? 1 : 0;
|
|
@@ -26,6 +35,9 @@ class FrameQueue {
|
|
|
26
35
|
this.latest = null;
|
|
27
36
|
}
|
|
28
37
|
}
|
|
38
|
+
function ownFrame(frame) {
|
|
39
|
+
return { ...frame, data: Buffer.from(frame.data) };
|
|
40
|
+
}
|
|
29
41
|
class Semaphore {
|
|
30
42
|
_concurrency;
|
|
31
43
|
_available;
|
|
@@ -194,6 +206,9 @@ class PipelineTimingSampler {
|
|
|
194
206
|
this.audioSamples.clear();
|
|
195
207
|
}
|
|
196
208
|
}
|
|
209
|
+
function ownDetectionEntry(entry) {
|
|
210
|
+
return { frame: ownFrame(entry.frame), handle: entry.handle };
|
|
211
|
+
}
|
|
197
212
|
const DEFAULT_MOTION_COOLDOWN_MS = 3e4;
|
|
198
213
|
function toFrameInput$1(frame) {
|
|
199
214
|
return {
|
|
@@ -268,8 +283,11 @@ class PipelineRunner {
|
|
|
268
283
|
this.detectionStreamHandler = handler;
|
|
269
284
|
}
|
|
270
285
|
registerCamera(deviceId, registration) {
|
|
271
|
-
const motionQueue = new FrameQueue(this.config.maxQueueDepth);
|
|
272
|
-
const detectionQueue = new FrameQueue(
|
|
286
|
+
const motionQueue = new FrameQueue(this.config.maxQueueDepth, ownFrame);
|
|
287
|
+
const detectionQueue = new FrameQueue(
|
|
288
|
+
this.config.maxQueueDepth,
|
|
289
|
+
ownDetectionEntry
|
|
290
|
+
);
|
|
273
291
|
const initialPhase = registration.detectionMode === "disabled" ? "idle" : registration.detectionMode === "always-on" ? "active" : "watching";
|
|
274
292
|
const state = {
|
|
275
293
|
registration,
|
|
@@ -324,12 +342,12 @@ class PipelineRunner {
|
|
|
324
342
|
if (!state) return;
|
|
325
343
|
state.motionQueue.enqueue(frame);
|
|
326
344
|
}
|
|
327
|
-
enqueueDetectionFrame(deviceId, frame) {
|
|
345
|
+
enqueueDetectionFrame(deviceId, frame, handle) {
|
|
328
346
|
const state = this.cameras.get(deviceId);
|
|
329
347
|
if (!state) return;
|
|
330
348
|
if (state.phase !== "active") return;
|
|
331
349
|
frame._enqueuedAt = Date.now();
|
|
332
|
-
state.detectionQueue.enqueue(frame);
|
|
350
|
+
state.detectionQueue.enqueue({ frame, handle });
|
|
333
351
|
}
|
|
334
352
|
/**
|
|
335
353
|
* Report a motion event for a camera. Drives the unified phase
|
|
@@ -482,9 +500,9 @@ class PipelineRunner {
|
|
|
482
500
|
if (this.semaphore.available <= 0) return;
|
|
483
501
|
const picked = this.pickNextDetectionFrame();
|
|
484
502
|
if (!picked) return;
|
|
485
|
-
const { deviceId,
|
|
486
|
-
const frameInput = toFrameInput$1(frame);
|
|
487
|
-
void this.processWithSemaphore(deviceId,
|
|
503
|
+
const { deviceId, entry, state } = picked;
|
|
504
|
+
const frameInput = toFrameInput$1(entry.frame);
|
|
505
|
+
void this.processWithSemaphore(deviceId, entry, frameInput, state, "detection");
|
|
488
506
|
}
|
|
489
507
|
drainMotionQueues() {
|
|
490
508
|
for (const [deviceId, state] of this.cameras) {
|
|
@@ -496,8 +514,9 @@ class PipelineRunner {
|
|
|
496
514
|
}
|
|
497
515
|
}
|
|
498
516
|
}
|
|
499
|
-
async processWithSemaphore(deviceId,
|
|
517
|
+
async processWithSemaphore(deviceId, entry, frameInput, state, streamType) {
|
|
500
518
|
const pickedAt = Date.now();
|
|
519
|
+
const { frame, handle } = entry;
|
|
501
520
|
const captureTs = frame.timestamp;
|
|
502
521
|
const enqueuedAt = frame._enqueuedAt ?? captureTs;
|
|
503
522
|
const release = await this.semaphore.acquire();
|
|
@@ -512,7 +531,7 @@ class PipelineRunner {
|
|
|
512
531
|
}
|
|
513
532
|
state.processedCount++;
|
|
514
533
|
if (result) {
|
|
515
|
-
await this.notifyCallbacks(deviceId, frame, result, streamType);
|
|
534
|
+
await this.notifyCallbacks(deviceId, frame, result, streamType, handle);
|
|
516
535
|
const emittedAt = Date.now();
|
|
517
536
|
this.timingSampler.addSample(deviceId, {
|
|
518
537
|
captureToEnqueue: enqueuedAt - captureTs,
|
|
@@ -528,10 +547,10 @@ class PipelineRunner {
|
|
|
528
547
|
release();
|
|
529
548
|
}
|
|
530
549
|
}
|
|
531
|
-
async notifyCallbacks(deviceId, frame, result, streamType) {
|
|
550
|
+
async notifyCallbacks(deviceId, frame, result, streamType, handle) {
|
|
532
551
|
for (const callback of this.resultCallbacks) {
|
|
533
552
|
try {
|
|
534
|
-
await callback(deviceId, frame, result, streamType);
|
|
553
|
+
await callback(deviceId, frame, result, streamType, handle);
|
|
535
554
|
} catch {
|
|
536
555
|
}
|
|
537
556
|
}
|
|
@@ -539,8 +558,8 @@ class PipelineRunner {
|
|
|
539
558
|
pickNextDetectionFrame() {
|
|
540
559
|
for (const [deviceId, state] of this.cameras) {
|
|
541
560
|
if (state.registration.detectionMode === "always-on" && state.detectionQueue.size > 0) {
|
|
542
|
-
const
|
|
543
|
-
return { deviceId,
|
|
561
|
+
const entry = state.detectionQueue.dequeue();
|
|
562
|
+
return { deviceId, entry, state };
|
|
544
563
|
}
|
|
545
564
|
}
|
|
546
565
|
if (this.defaultRoundRobinKeys.length === 0) return null;
|
|
@@ -553,14 +572,75 @@ class PipelineRunner {
|
|
|
553
572
|
if (!state) continue;
|
|
554
573
|
if (state.phase === "active" && state.detectionQueue.size > 0) {
|
|
555
574
|
this.defaultRoundRobinIndex = (idx + 1) % this.defaultRoundRobinKeys.length;
|
|
556
|
-
const
|
|
557
|
-
if (!
|
|
558
|
-
return { deviceId,
|
|
575
|
+
const entry = state.detectionQueue.dequeue();
|
|
576
|
+
if (!entry) continue;
|
|
577
|
+
return { deviceId, entry, state };
|
|
559
578
|
}
|
|
560
579
|
}
|
|
561
580
|
return null;
|
|
562
581
|
}
|
|
563
582
|
}
|
|
583
|
+
const PULL_MAX_COUNT = 4;
|
|
584
|
+
const MIN_POLL_INTERVAL_MS = 20;
|
|
585
|
+
const FALLBACK_POLL_INTERVAL_MS = 200;
|
|
586
|
+
async function startFrameHandlePoller(options) {
|
|
587
|
+
const { api, brokerId, format, maxFps, tag, onFrame, logger } = options;
|
|
588
|
+
let result;
|
|
589
|
+
try {
|
|
590
|
+
result = await api.streamBroker.subscribeFrames.mutate({
|
|
591
|
+
brokerId,
|
|
592
|
+
format,
|
|
593
|
+
maxFps,
|
|
594
|
+
tag
|
|
595
|
+
});
|
|
596
|
+
} catch (err) {
|
|
597
|
+
logger.warn("frame-handle poller: subscribeFrames failed", {
|
|
598
|
+
meta: { brokerId, format, tag, error: errMsg(err) }
|
|
599
|
+
});
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
const { subscriptionId } = result;
|
|
603
|
+
const readers = new FrameRingReaderCache(logger);
|
|
604
|
+
const pollIntervalMs = result.maxFps > 0 ? Math.max(MIN_POLL_INTERVAL_MS, Math.round(1e3 / result.maxFps)) : FALLBACK_POLL_INTERVAL_MS;
|
|
605
|
+
let stopped = false;
|
|
606
|
+
let timer;
|
|
607
|
+
const tick = async () => {
|
|
608
|
+
if (stopped) return;
|
|
609
|
+
try {
|
|
610
|
+
const handles = await api.streamBroker.pullFrameHandles.query({
|
|
611
|
+
subscriptionId,
|
|
612
|
+
maxCount: PULL_MAX_COUNT
|
|
613
|
+
});
|
|
614
|
+
for (const handle of handles) {
|
|
615
|
+
if (stopped) break;
|
|
616
|
+
const frame = readers.read(handle);
|
|
617
|
+
if (frame) onFrame(frame, handle);
|
|
618
|
+
}
|
|
619
|
+
} catch (err) {
|
|
620
|
+
logger.warn("frame-handle poller: pullFrameHandles failed", {
|
|
621
|
+
meta: { brokerId, subscriptionId, error: errMsg(err) }
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
if (!stopped) {
|
|
625
|
+
timer = setTimeout(() => void tick(), pollIntervalMs);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
void tick();
|
|
629
|
+
return () => {
|
|
630
|
+
if (stopped) return;
|
|
631
|
+
stopped = true;
|
|
632
|
+
if (timer) {
|
|
633
|
+
clearTimeout(timer);
|
|
634
|
+
timer = void 0;
|
|
635
|
+
}
|
|
636
|
+
readers.close();
|
|
637
|
+
api.streamBroker.unsubscribeFrames.mutate({ subscriptionId }).catch((err) => {
|
|
638
|
+
logger.warn("frame-handle poller: unsubscribeFrames failed", {
|
|
639
|
+
meta: { brokerId, subscriptionId, error: errMsg(err) }
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
};
|
|
643
|
+
}
|
|
564
644
|
const BenchEngineChoiceSchema = object({
|
|
565
645
|
runtime: _enum(["node", "python"]),
|
|
566
646
|
backend: string(),
|
|
@@ -721,8 +801,8 @@ class PipelineRunnerAddon extends BaseAddon {
|
|
|
721
801
|
this.runner.onDetectionStreamChange((deviceId, action) => {
|
|
722
802
|
this.handleDetectionStreamChange(deviceId, action);
|
|
723
803
|
});
|
|
724
|
-
this.runner.onResult(async (deviceId, frame, result, _streamType) => {
|
|
725
|
-
this.emitInferenceResult(deviceId, frame, result);
|
|
804
|
+
this.runner.onResult(async (deviceId, frame, result, _streamType, handle) => {
|
|
805
|
+
this.emitInferenceResult(deviceId, frame, result, handle);
|
|
726
806
|
});
|
|
727
807
|
this.runner.start();
|
|
728
808
|
this.ctx.logger.info(
|
|
@@ -1276,18 +1356,19 @@ class PipelineRunnerAddon extends BaseAddon {
|
|
|
1276
1356
|
log.warn("subscribeMotionFrames: this.ctx.api not available");
|
|
1277
1357
|
return null;
|
|
1278
1358
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1359
|
+
return startFrameHandlePoller({
|
|
1360
|
+
api,
|
|
1361
|
+
brokerId: `${config.deviceId}/${config.motionStreamId}`,
|
|
1362
|
+
format: "gray",
|
|
1363
|
+
maxFps: config.motionFps,
|
|
1364
|
+
tag: "motion",
|
|
1365
|
+
logger: log,
|
|
1366
|
+
// Motion analysis is intra-process and never propagates beyond
|
|
1367
|
+
// the runner; the handle is intentionally ignored here.
|
|
1368
|
+
onFrame: (frame, _handle) => {
|
|
1287
1369
|
runner.enqueueMotionFrame(config.deviceId, frame);
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
);
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1291
1372
|
}
|
|
1292
1373
|
handleDetectionStreamChange(deviceId, action) {
|
|
1293
1374
|
const attachment = this.attached.get(deviceId);
|
|
@@ -1361,23 +1442,20 @@ class PipelineRunnerAddon extends BaseAddon {
|
|
|
1361
1442
|
log.warn("subscribeDetectionFrames: this.ctx.api not available");
|
|
1362
1443
|
return null;
|
|
1363
1444
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
// once per frame via its conversion cache — no double work.
|
|
1379
|
-
{ maxFps: config.detectionFps, format: "rgb", tag: "detection" }
|
|
1380
|
-
);
|
|
1445
|
+
return startFrameHandlePoller({
|
|
1446
|
+
api,
|
|
1447
|
+
brokerId: `${config.deviceId}/${config.detectionStreamId}`,
|
|
1448
|
+
format: "rgb",
|
|
1449
|
+
maxFps: config.detectionFps,
|
|
1450
|
+
tag: "detection",
|
|
1451
|
+
logger: log,
|
|
1452
|
+
// Detection threads the `FrameHandle` through the runner so the
|
|
1453
|
+
// emitted `PipelineInferenceResultPayload` can name the shm slot
|
|
1454
|
+
// post-analysis (Task 8) reads pixels back from.
|
|
1455
|
+
onFrame: (frame, handle) => {
|
|
1456
|
+
runner.enqueueDetectionFrame(config.deviceId, frame, handle);
|
|
1457
|
+
}
|
|
1458
|
+
});
|
|
1381
1459
|
}
|
|
1382
1460
|
// ── Internal: inference + motion callbacks ───────────────────────────
|
|
1383
1461
|
async runInference(deviceId, frame) {
|
|
@@ -1494,13 +1572,14 @@ class PipelineRunnerAddon extends BaseAddon {
|
|
|
1494
1572
|
log.error("runMotionAnalysis failed", { meta: { error: msg } });
|
|
1495
1573
|
}
|
|
1496
1574
|
}
|
|
1497
|
-
emitInferenceResult(deviceId, _frame, result) {
|
|
1575
|
+
emitInferenceResult(deviceId, _frame, result, handle) {
|
|
1498
1576
|
const ctx = this.ctx;
|
|
1499
1577
|
if (!ctx?.eventBus) return;
|
|
1500
1578
|
const payload = {
|
|
1501
1579
|
deviceId,
|
|
1502
1580
|
frame: result,
|
|
1503
|
-
nodeId: this.nodeId
|
|
1581
|
+
nodeId: this.nodeId,
|
|
1582
|
+
frameHandle: handle
|
|
1504
1583
|
};
|
|
1505
1584
|
this.ctx.eventBus.emit(createEvent(
|
|
1506
1585
|
EventCategory.PipelineInferenceResult,
|