@camstack/addon-pipeline 1.2.107 → 1.2.118

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.
Files changed (35) hide show
  1. package/dist/{addon-utils-A2S9D7pu.mjs → addon-utils-CgBCF-mE.mjs} +50 -14
  2. package/dist/{addon-utils-Vv2dCqA2.js → addon-utils-DJSN5h8c.js} +51 -15
  3. package/dist/audio-analyzer/index.js +3 -3
  4. package/dist/audio-analyzer/index.mjs +3 -3
  5. package/dist/detection-pipeline/index.js +170 -31
  6. package/dist/detection-pipeline/index.mjs +169 -30
  7. package/dist/{dist-CkXAzTZ2.mjs → dist-B763E61Y.mjs} +152 -26
  8. package/dist/{dist-L-1LMGQs.js → dist-BkO76jAp.js} +152 -26
  9. package/dist/{event-loop-stall-monitor-DwAho7HD.js → event-loop-stall-monitor-28f4R0JN.js} +234 -1
  10. package/dist/{event-loop-stall-monitor-fHkfgmlw.mjs → event-loop-stall-monitor-CYEvvp2Z.mjs} +223 -2
  11. package/dist/{lazy-sharp-DfbyQxET.js → lazy-sharp-BaPl5mRa.js} +1 -1
  12. package/dist/motion-wasm/index.js +2 -2
  13. package/dist/motion-wasm/index.mjs +1 -1
  14. package/dist/pipeline-runner/index.js +915 -107
  15. package/dist/pipeline-runner/index.mjs +914 -106
  16. package/dist/{process-memory-CgrbLo3l.js → process-memory-BCQJFZZg.js} +1 -1
  17. package/dist/{process-memory-DlSOzuHP.mjs → process-memory-CK3FnKyZ.mjs} +1 -1
  18. package/dist/recorder/index.js +446 -77
  19. package/dist/recorder/index.mjs +446 -77
  20. package/dist/session-decode/decode-worker-child.js +62 -34
  21. package/dist/session-decode/decode-worker-child.mjs +61 -33
  22. package/dist/stream-broker/_stub.js +2 -2
  23. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BeL4_jgH.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CxgvfkxP.mjs} +3 -3
  24. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CL6Lgzdj.mjs +26 -0
  25. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CmHtm5CX.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BAMyzCWw.mjs} +1 -1
  26. package/dist/stream-broker/{hostInit-BK9nzKAG.mjs → hostInit-CTkpxp3w.mjs} +3 -3
  27. package/dist/stream-broker/index.js +279 -198
  28. package/dist/stream-broker/index.mjs +279 -198
  29. package/dist/stream-broker/remoteEntry.js +1 -1
  30. package/dist/{worker-protocol-bEipQT9l.mjs → worker-protocol-D_2QaXYr.mjs} +6 -3
  31. package/dist/{worker-protocol-GGnzfWu3.js → worker-protocol-owR7WMRP.js} +6 -3
  32. package/package.json +1 -1
  33. package/python/inference_pool.py +4 -1
  34. package/python/test_inference_pool_preprocess.py +87 -16
  35. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DjndFc5V.mjs +0 -26
@@ -1,9 +1,9 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { $ as pickClusterStepSettings, At as nodePin, D as YAMNET_TO_MACRO, Et as hydrateSchema, G as evaluateZoneRules, Gt as union, Ht as object, I as defaultDeviceFor$1, It as array, Kt as EventCategory, Pt as sleep, Q as pickClusterStepModels, Tt as createEvent, V as detectionPipelineCapability, W as enumerateInferenceDevices, Wt as string, X as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as resolvePoolMemoryPolicy, ht as errMsg, jt as parseJsonUnknown, l as DEFAULT_CLUSTER_STEP_SETTINGS, nt as pipelineExecutorCapability, ot as resolveClusterStepModelId, p as DEVICE_BACKEND_TO_FORMAT, pt as supportedRuntimes$1, t as APPLE_SA_TO_MACRO, ut as runtimeDevices$1, x as PoolMemoryWatchdog, xt as BaseAddon } from "../dist-CkXAzTZ2.mjs";
3
- import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, n as startEventLoopStallMonitor, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, u as landmarkPrecisionVerdict } from "../event-loop-stall-monitor-fHkfgmlw.mjs";
2
+ import { $ as pickClusterStepSettings, At as nodePin, D as YAMNET_TO_MACRO, Et as hydrateSchema, G as evaluateZoneRules, Gt as union, Ht as object, I as defaultDeviceFor$1, It as array, Kt as EventCategory, Pt as sleep, Q as pickClusterStepModels, Tt as createEvent, V as detectionPipelineCapability, W as enumerateInferenceDevices, Wt as string, X as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as resolvePoolMemoryPolicy, ht as errMsg, jt as parseJsonUnknown, l as DEFAULT_CLUSTER_STEP_SETTINGS, nt as pipelineExecutorCapability, ot as resolveClusterStepModelId, p as DEVICE_BACKEND_TO_FORMAT, pt as supportedRuntimes$1, t as APPLE_SA_TO_MACRO, ut as runtimeDevices$1, x as PoolMemoryWatchdog, xt as BaseAddon } from "../dist-B763E61Y.mjs";
3
+ import { a as ALL_PIPELINE_STEPS, c as getDefaultModelForFormatFromDef, d as resolveModelForFormat, f as landmarkPrecisionVerdict, l as getStep, n as startEventLoopStallMonitor, o as ALL_STEPS, r as localFrameRegistry, s as getDefaultModelForFormat, u as getStepDefinition } from "../event-loop-stall-monitor-CYEvvp2Z.mjs";
4
4
  import { t as getSharp } from "../lazy-sharp-6oymT_yf.mjs";
5
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DlSOzuHP.mjs";
6
- import { a as ensureModel, o as isModelDownloaded, r as deleteModelFromDisk } from "../addon-utils-A2S9D7pu.mjs";
5
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-CK3FnKyZ.mjs";
6
+ import { a as ensureModel, o as isModelDownloaded, r as deleteModelFromDisk } from "../addon-utils-CgBCF-mE.mjs";
7
7
  import sharp from "sharp";
8
8
  import { spawn } from "node:child_process";
9
9
  import * as path$1 from "node:path";
@@ -257,7 +257,13 @@ var OBJECT_DETECTION_STEP_ID = "object-detection";
257
257
  * `null` → the caller substitutes the step's own `defaultModelId` (`yolo26n`).
258
258
  * INTEL NPU + iGPU default to OUR YOLOv9 (int8 @320): yolo26 does NOT compile on
259
259
  * the Intel NPU (arch incompat → 0 frames), while yolov9 runs on it (~298 fps
260
- * measured). Apple ANE stays on yolo26 until the CoreML yolov9 build lands.
260
+ * measured). Apple ANE uses the CoreML yolov9 @320 build.
261
+ *
262
+ * Do **not** promote these ids to `yolov9m-640` / `*-640`. The controlled
263
+ * evaluation recovered 0/3 misses at the current 0.50 threshold and failed the
264
+ * false-positive and capacity gates — see
265
+ * `docs/benchmarks/pipeline-frame-model-eval.md`. 640 remains an explicit
266
+ * operator pick, not a hardware-aware default.
261
267
  */
262
268
  var MODEL_BY_CLASS = {
263
269
  "apple-ane": "yolov9m-320",
@@ -1367,7 +1373,7 @@ function macroOfMinConfidenceKey(key) {
1367
1373
  */
1368
1374
  function reachableMacros(def, entry) {
1369
1375
  if (entry.labels.length === 0) return void 0;
1370
- const map = def.classMap;
1376
+ const map = entry.classMap ?? def.classMap;
1371
1377
  if (!map) return new Set(entry.labels.map((l) => l.id));
1372
1378
  if (map.preserveOriginal) return void 0;
1373
1379
  const macros = /* @__PURE__ */ new Set();
@@ -1387,7 +1393,7 @@ function reachableMacros(def, entry) {
1387
1393
  */
1388
1394
  function collectClassMapDropWarning(def, entry) {
1389
1395
  if (entry.labels.length === 0) return null;
1390
- const map = def.classMap;
1396
+ const map = entry.classMap ?? def.classMap;
1391
1397
  if (!map || map.preserveOriginal) return null;
1392
1398
  const unmapped = entry.labels.filter((l) => map.mapping[l.id] === void 0).map((l) => l.id);
1393
1399
  if (unmapped.length === 0) return null;
@@ -4163,7 +4169,7 @@ function applyChildOutput(parent, childStep, output, stepLatencyMs, ctx) {
4163
4169
  switch (output.kind) {
4164
4170
  case "detections":
4165
4171
  if (childStep.definition.slot === "refiner") {
4166
- const classMap = childStep.definition.classMap?.mapping;
4172
+ const classMap = childStep.effectiveClassMap?.mapping;
4167
4173
  const parentMacro = parent.macroClass;
4168
4174
  const best = output.detections.filter((d) => {
4169
4175
  if (d.mask === void 0) return false;
@@ -4503,6 +4509,29 @@ function reprojectCropZoneDetections(output, cropOrigin) {
4503
4509
  }))
4504
4510
  };
4505
4511
  }
4512
+ function reprojectViewDetections(output, geometry) {
4513
+ const mapPoint = (x, y) => ({
4514
+ x: geometry.sourceCrop.left + x / geometry.scale.x,
4515
+ y: geometry.sourceCrop.top + y / geometry.scale.y
4516
+ });
4517
+ return {
4518
+ kind: "detections",
4519
+ detections: output.detections.map((det) => {
4520
+ const origin = mapPoint(det.bbox[0], det.bbox[1]);
4521
+ const end = mapPoint(det.bbox[2], det.bbox[3]);
4522
+ return {
4523
+ ...det,
4524
+ bbox: [
4525
+ origin.x,
4526
+ origin.y,
4527
+ end.x,
4528
+ end.y
4529
+ ],
4530
+ ...det.landmarks ? { landmarks: det.landmarks.map((landmark) => mapPoint(landmark.x, landmark.y)) } : {}
4531
+ };
4532
+ })
4533
+ };
4534
+ }
4506
4535
  var PipelineExecutor = class {
4507
4536
  opts;
4508
4537
  /** Bounds the full-frame-guard drop log: first example per (device,
@@ -4564,7 +4593,7 @@ var PipelineExecutor = class {
4564
4593
  *
4565
4594
  * @returns FrameResult + optional trace
4566
4595
  */
4567
- async run(tree, rootInput, fullFrameJpegProvider, imageWidth, imageHeight, deviceId, runOpts, nativeCropProvider, cropZoneBbox) {
4596
+ async run(tree, rootInput, fullFrameJpegProvider, imageWidth, imageHeight, deviceId, runOpts, nativeCropProvider, cropZoneBbox, rootInputViewProvider) {
4568
4597
  const startMs = Date.now();
4569
4598
  const verbosity = runOpts?.traceVerbosity ?? "off";
4570
4599
  const traceBuilder = new ExecutionTraceBuilder(verbosity, deviceId, imageWidth, imageHeight, this.opts.engineRuntime);
@@ -4612,18 +4641,20 @@ var PipelineExecutor = class {
4612
4641
  };
4613
4642
  for (const rootStep of tree.roots) {
4614
4643
  if (debug) console.log(`[executor] rootStep=${rootStep.stepId} settings=${JSON.stringify(rootStep.settings ?? {})}`);
4615
- const cropPrep = rootStep.definition.extractMode === "crop-zone" && cropZoneBbox !== void 0 ? await this.prepareCropZoneInput(cropZoneBbox, fullFrameJpegProvider, imageWidth, imageHeight, deviceId) : null;
4644
+ const rootCrop = rootStep.definition.extractMode === "crop-zone" ? cropZoneBbox : void 0;
4645
+ const rootView = rootInputViewProvider ? await rootInputViewProvider(rootStep, rootCrop) : null;
4646
+ const cropPrep = !rootView && rootCrop !== void 0 ? await this.prepareCropZoneInput(rootCrop, fullFrameJpegProvider, imageWidth, imageHeight, deviceId) : null;
4616
4647
  const rootStart = Date.now();
4617
- const rawRootOutput = await this.executeStep(rootStep, cropPrep?.input ?? withInferenceDeviceId(rootInput, deviceId), cropPrep?.width ?? imageWidth, cropPrep?.height ?? imageHeight, "full-frame", void 0, void 0, traceBuilder, stepTimings, poolAgg, rootShed);
4648
+ const rawRootOutput = await this.executeStep(rootStep, rootView?.input ?? cropPrep?.input ?? withInferenceDeviceId(rootInput, deviceId), rootView?.width ?? cropPrep?.width ?? imageWidth, rootView?.height ?? cropPrep?.height ?? imageHeight, "full-frame", void 0, void 0, traceBuilder, stepTimings, poolAgg, rootShed);
4618
4649
  const rootMs = Date.now() - rootStart;
4619
4650
  if (rawRootOutput === null) continue;
4620
- const rootOutput = cropPrep && rawRootOutput.kind === "detections" ? reprojectCropZoneDetections(rawRootOutput, cropPrep.origin) : rawRootOutput;
4651
+ const rootOutput = rootView && rawRootOutput.kind === "detections" ? reprojectViewDetections(rawRootOutput, rootView.geometry) : cropPrep && rawRootOutput.kind === "detections" ? reprojectCropZoneDetections(rawRootOutput, cropPrep.origin) : rawRootOutput;
4621
4652
  if (rootOutput.kind !== "detections") {
4622
4653
  if (isEnrichmentOutput(rootOutput)) {
4623
4654
  const mutable = this.synthesizeRootDetection(rootOutput, rootStep, idGen, rootMs, imageWidth, imageHeight);
4624
4655
  applyChildOutput(mutable, rootStep, rootOutput, rootMs, ctx);
4625
4656
  try {
4626
- await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeCropProvider);
4657
+ await this.executeChildren(rootStep.children, mutable, rootView?.jpegProvider ?? fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeCropProvider);
4627
4658
  } catch (err) {
4628
4659
  this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
4629
4660
  tags: { deviceId },
@@ -4641,12 +4672,12 @@ var PipelineExecutor = class {
4641
4672
  }
4642
4673
  for (const det of rootOutput.detections) {
4643
4674
  const mutable = toMutableRootDetection(det, rootStep, idGen, rootMs);
4644
- if (rootStep.definition.classMap) {
4645
- const mapped = rootStep.definition.classMap.mapping[det.class];
4675
+ if (rootStep.effectiveClassMap) {
4676
+ const mapped = rootStep.effectiveClassMap.mapping[det.class];
4646
4677
  if (mapped) {
4647
4678
  mutable.originalClass = det.class;
4648
4679
  mutable.macroClass = mapped;
4649
- } else if (!rootStep.definition.classMap.preserveOriginal) {
4680
+ } else if (!rootStep.effectiveClassMap.preserveOriginal) {
4650
4681
  (discarded ??= []).push({
4651
4682
  bbox: [
4652
4683
  mutable.bbox[0],
@@ -4728,7 +4759,7 @@ var PipelineExecutor = class {
4728
4759
  }
4729
4760
  });
4730
4761
  try {
4731
- await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeCropProvider);
4762
+ await this.executeChildren(rootStep.children, mutable, rootView?.jpegProvider ?? fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeCropProvider);
4732
4763
  } catch (err) {
4733
4764
  this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
4734
4765
  tags: { deviceId },
@@ -5148,6 +5179,59 @@ function capitalize(s) {
5148
5179
  return s.charAt(0).toUpperCase() + s.slice(1);
5149
5180
  }
5150
5181
  //#endregion
5182
+ //#region src/session-decode/frame-view-payload.ts
5183
+ var FRAME_VIEW_PAYLOAD_POLICY = "jpeg";
5184
+ //#endregion
5185
+ //#region src/detection-pipeline/root-frame-view.ts
5186
+ /** Resolve the pre-padding content requested from the decode worker for one root. */
5187
+ function resolveRootFrameViewSpec(model, source, crop, format = FRAME_VIEW_PAYLOAD_POLICY) {
5188
+ const sourceWidth = crop?.width ?? source.width;
5189
+ const sourceHeight = crop?.height ?? source.height;
5190
+ if (model.preprocessMode !== "letterbox") return {
5191
+ ...crop ? { crop } : {},
5192
+ content: {
5193
+ width: model.inputSize.width,
5194
+ height: model.inputSize.height
5195
+ },
5196
+ fit: "stretch",
5197
+ format
5198
+ };
5199
+ const scale = Math.min(model.inputSize.width / sourceWidth, model.inputSize.height / sourceHeight);
5200
+ return {
5201
+ ...crop ? { crop } : {},
5202
+ content: {
5203
+ width: Math.max(1, Math.round(sourceWidth * scale)),
5204
+ height: Math.max(1, Math.round(sourceHeight * scale))
5205
+ },
5206
+ fit: "contain",
5207
+ format
5208
+ };
5209
+ }
5210
+ //#endregion
5211
+ //#region src/detection-pipeline/frame-ref-view-provider.ts
5212
+ var LocalFrameRefMissError = class extends Error {
5213
+ reason;
5214
+ constructor(reason) {
5215
+ super(`local frameRef miss: ${reason}`);
5216
+ this.reason = reason;
5217
+ this.name = "LocalFrameRefMissError";
5218
+ }
5219
+ };
5220
+ /** Bind one registry lease for all heterogeneous roots of a pipeline invocation. */
5221
+ function createRootFrameViewResolver(registry, ref) {
5222
+ const lease = registry.acquire(ref);
5223
+ if (!lease) throw new LocalFrameRefMissError(ref.registryId === registry.registryId ? "stale-ref" : "foreign-registry");
5224
+ const resolve = async (root, crop) => {
5225
+ const model = root.definition.models.find((candidate) => candidate.id === root.modelId);
5226
+ if (!model) throw new Error(`frame view model not found: ${root.modelId}`);
5227
+ const spec = resolveRootFrameViewSpec(model, ref, crop);
5228
+ const result = await lease.resolve(spec);
5229
+ if (result.kind === "miss") throw new LocalFrameRefMissError(result.reason);
5230
+ return result;
5231
+ };
5232
+ return Object.assign(resolve, { release: (reason) => lease.release(reason) });
5233
+ }
5234
+ //#endregion
5151
5235
  //#region src/detection-pipeline/pipeline/native-crop-compose.ts
5152
5236
  /** Clamp `v` into `[lo, hi]`. */
5153
5237
  function clamp(v, lo, hi) {
@@ -5187,23 +5271,32 @@ function composeCropRoiToFrameNorm(roi, cropFrameSpace, frameWidth, frameHeight)
5187
5271
  //#endregion
5188
5272
  //#region src/detection-pipeline/pipeline/tree-builder.ts
5189
5273
  /**
5274
+ * Effective class map for `(definition, modelId)` without writing back to the
5275
+ * shared StepDefinition. Custom models missing from `definition.models` are
5276
+ * resolved through the optional registry callback.
5277
+ */
5278
+ function resolveEffectiveClassMap(definition, modelId, resolveModel) {
5279
+ return (definition.models.find((model) => model.id === modelId) ?? resolveModel?.(definition.id, modelId))?.classMap ?? definition.classMap;
5280
+ }
5281
+ /**
5190
5282
  * Build an executable tree from user config.
5191
5283
  *
5192
5284
  * @param steps - User-configured pipeline steps (from PipelineDefaultStep[])
5193
5285
  * @param getEngine - Function that returns an IInferenceEngine for a step ID.
5194
5286
  * Throws if step not loaded.
5195
5287
  */
5196
- function buildExecutableTree(steps, getEngine) {
5197
- return { roots: steps.filter((s) => s.enabled).filter((s) => s.slot !== "audio-classifier").map((s) => buildNode(s, getEngine)) };
5288
+ function buildExecutableTree(steps, getEngine, resolveModel) {
5289
+ return { roots: steps.filter((s) => s.enabled).filter((s) => s.slot !== "audio-classifier").map((s) => buildNode(s, getEngine, resolveModel)) };
5198
5290
  }
5199
- function buildNode(step, getEngine) {
5291
+ function buildNode(step, getEngine, resolveModel) {
5200
5292
  const definition = getStepDefinition(step.addonId);
5201
5293
  const engine = getEngine(step.addonId);
5202
- const children = (step.children ?? []).filter((c) => c.enabled).map((c) => buildNode(c, getEngine));
5294
+ const children = (step.children ?? []).filter((c) => c.enabled).map((c) => buildNode(c, getEngine, resolveModel));
5203
5295
  const mergedSettings = {
5204
5296
  ...collectSchemaDefaults(step.addonId),
5205
5297
  ...step.settings
5206
5298
  };
5299
+ const effectiveClassMap = resolveEffectiveClassMap(definition, step.modelId, resolveModel);
5207
5300
  return {
5208
5301
  stepId: step.addonId,
5209
5302
  definition,
@@ -5212,7 +5305,8 @@ function buildNode(step, getEngine) {
5212
5305
  inputClasses: definition.inputClasses ?? [],
5213
5306
  enabled: step.enabled,
5214
5307
  children,
5215
- ...Object.keys(mergedSettings).length > 0 ? { settings: mergedSettings } : {}
5308
+ ...Object.keys(mergedSettings).length > 0 ? { settings: mergedSettings } : {},
5309
+ ...effectiveClassMap !== void 0 ? { effectiveClassMap } : {}
5216
5310
  };
5217
5311
  }
5218
5312
  /**
@@ -7091,17 +7185,30 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
7091
7185
  let jpegProvider;
7092
7186
  const sources = [
7093
7187
  input.frame ? "frame" : null,
7188
+ input.frameRef ? "frameRef" : null,
7094
7189
  input.frameHandle ? "frameHandle" : null,
7095
7190
  input.image ? "image" : null,
7096
7191
  input.imageBase64 ? "imageBase64" : null,
7097
7192
  input.referenceImage ? "referenceImage" : null
7098
7193
  ].filter((s) => s !== null);
7099
- if (sources.length === 0) throw new Error("runPipeline requires exactly one of: frame, frameHandle, image, imageBase64, referenceImage");
7194
+ if (sources.length === 0) throw new Error("runPipeline requires exactly one of: frame, frameRef, frameHandle, image, imageBase64, referenceImage");
7100
7195
  if (sources.length > 1) throw new Error(`runPipeline received conflicting image sources: ${sources.join(", ")}`);
7101
7196
  if (input.frameHandle) return this.emptyFrameHandleResult(input);
7102
7197
  const runtimeFrame = input.frame ?? void 0;
7198
+ const runtimeFrameRef = input.frameRef;
7103
7199
  const decodeT0 = performance.now();
7104
- if (runtimeFrame) {
7200
+ if (runtimeFrameRef) {
7201
+ imageWidth = runtimeFrameRef.width;
7202
+ imageHeight = runtimeFrameRef.height;
7203
+ rootInput = {
7204
+ kind: "jpeg",
7205
+ data: Buffer.alloc(0)
7206
+ };
7207
+ jpegProvider = async () => {
7208
+ throw new Error("frameRef root view was requested before model resolution");
7209
+ };
7210
+ emit(`FrameRef: ${imageWidth}×${imageHeight} (${runtimeFrameRef.format})`);
7211
+ } else if (runtimeFrame) {
7105
7212
  const frame = runtimeFrame;
7106
7213
  imageWidth = frame.width;
7107
7214
  imageHeight = frame.height;
@@ -7301,9 +7408,9 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
7301
7408
  emit(`All models loaded`);
7302
7409
  }
7303
7410
  emit("Running inference...");
7304
- const tree = buildExecutableTree(benchmarkSteps, (stepId) => dispatchFactory.getEngine(stepId));
7411
+ const tree = buildExecutableTree(benchmarkSteps, (stepId) => dispatchFactory.getEngine(stepId), this.customModelResolver);
7305
7412
  setupMs = performance.now() - wallT0 - decodeMs;
7306
- const isRuntime = Boolean(runtimeFrame);
7413
+ const isRuntime = Boolean(runtimeFrame || runtimeFrameRef);
7307
7414
  const effectiveDeviceId = input.deviceId ?? 0;
7308
7415
  const deviceOverrides = effectiveDeviceId > 0 ? await this.readDeviceStore(effectiveDeviceId) : {};
7309
7416
  const effectiveTree = Object.keys(deviceOverrides).length > 0 ? applyDeviceOverridesToTree(tree, "object-detection", deviceOverrides) : tree;
@@ -7314,10 +7421,42 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
7314
7421
  const proxy = this.deviceProxies.get(effectiveDeviceId);
7315
7422
  if (proxy) cropZoneBbox = resolvePackageCropBbox(proxy.state.zones.value?.zones ?? [], proxy.state.zoneRules.value?.package ?? [], imageWidth, imageHeight) ?? void 0;
7316
7423
  }
7317
- const { result, trace } = await executor.run(effectiveTree, rootInput, jpegProvider, imageWidth, imageHeight, effectiveDeviceId, {
7318
- traceVerbosity: isRuntime ? this.eventBus ? "summary" : "off" : "full",
7319
- plane: input.plane
7320
- }, nativeCropProvider, cropZoneBbox);
7424
+ let frameViewResolver;
7425
+ let rootInputViewProvider;
7426
+ if (runtimeFrameRef) {
7427
+ frameViewResolver = createRootFrameViewResolver(localFrameRegistry, runtimeFrameRef);
7428
+ rootInputViewProvider = async (root, crop) => {
7429
+ const view = await frameViewResolver(root, crop ? {
7430
+ left: crop[0],
7431
+ top: crop[1],
7432
+ width: crop[2] - crop[0],
7433
+ height: crop[3] - crop[1]
7434
+ } : void 0);
7435
+ const data = Buffer.from(view.data.buffer, view.data.byteOffset, view.data.byteLength);
7436
+ return {
7437
+ input: {
7438
+ kind: "jpeg",
7439
+ data
7440
+ },
7441
+ jpegProvider: async () => data,
7442
+ width: view.width,
7443
+ height: view.height,
7444
+ geometry: view.geometry
7445
+ };
7446
+ };
7447
+ }
7448
+ let executionSucceeded = false;
7449
+ let execution;
7450
+ try {
7451
+ execution = await executor.run(effectiveTree, rootInput, jpegProvider, imageWidth, imageHeight, effectiveDeviceId, {
7452
+ traceVerbosity: isRuntime ? this.eventBus ? "summary" : "off" : "full",
7453
+ plane: input.plane
7454
+ }, nativeCropProvider, cropZoneBbox, rootInputViewProvider);
7455
+ executionSucceeded = true;
7456
+ } finally {
7457
+ frameViewResolver?.release(executionSucceeded ? "success" : "error");
7458
+ }
7459
+ const { result, trace } = execution;
7321
7460
  if (isRuntime) {
7322
7461
  if (trace && this.eventBus) this.eventBus.emit(createEvent(EventCategory.PipelineTrace, {
7323
7462
  type: "device",