@camstack/addon-pipeline 1.2.327 → 1.2.328
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/THIRD_PARTY_MODELS.md +34 -26
- package/dist/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/{default-detection-model-CBIYdAJ5.js → default-detection-model-1SadEKsW.js} +118 -59
- package/dist/{default-detection-model-hql6BX9-.mjs → default-detection-model-CMeVTcPZ.mjs} +118 -59
- package/dist/detection-pipeline/index.js +48 -8
- package/dist/detection-pipeline/index.mjs +48 -8
- package/dist/{dist-B9LnBPz9.mjs → dist-Bpub2VcJ.mjs} +493 -369
- package/dist/{dist-BBZwYfSN.js → dist-wJO7mXeO.js} +540 -368
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-mJQBUiEc.js → node-BCrqaejt.js} +1 -1
- package/dist/{node-Ci0E-0VP.mjs → node-BjCSgD4M.mjs} +1 -1
- package/dist/pipeline-runner/index.js +215 -78
- package/dist/pipeline-runner/index.mjs +215 -78
- package/dist/{process-memory-B63Jlpev.mjs → process-memory-BaKQ8u2G.mjs} +1 -1
- package/dist/{process-memory-DgEfKdtC.js → process-memory-iUJuTpXs.js} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/{segment-demux-js-DzwHW4Ey.mjs → segment-demux-js-C5ez9LYG.mjs} +1 -1
- package/dist/{segment-demux-js-C2ufKMu0.js → segment-demux-js-Opx6Hv9G.js} +1 -1
- package/dist/session-decode/decode-worker-main.js +13 -21
- package/dist/session-decode/decode-worker-main.mjs +13 -21
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B4fPzS-8.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B94LgsV0.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BPWYf4_O.mjs +26 -0
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-Cg4IdtE5.mjs → hostInit-xOx7AvgW.mjs} +2 -2
- package/dist/stream-broker/index.js +4 -3
- package/dist/stream-broker/index.mjs +4 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/python/inference_pool.py +38 -121
- package/python/postprocessors/test_bird_edgetpu.py +124 -0
- package/python/postprocessors/testdata/bird_classifier_int8_outputs.json +1 -0
- package/python/test_inference_pool_static_batch.py +2 -4
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BDGzcgLP.mjs +0 -26
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
3
|
-
import { c as macroGateVerdict, d as isSessionDecodeReadGone, f as createSessionDecodeCoordinator, l as rootObjectGate, o as placeDetailStep, p as resolveFrameViewGeometry, r as CustomModelCatalog, s as stepsForElectedPool, u as localFrameRegistry, v as getStepDefinition } from "../default-detection-model-
|
|
1
|
+
import { Bn as array, Bt as pickDetailCropConvention, D as FailureCounters, Dn as customAction, Dt as loadContributionCapability, En as createEvent, Et as linkedStepOf, Gn as number, Kn as object, M as NativeLeaseAdmissionSchema, N as NativeLeaseSettingsSchema, On as defineCustomActions, Pn as nodePin, Q as cameraOwnsMotionViaSensor, Qt as resolveLabelLink, Sn as BaseAddon, Un as lazy, Ut as pipelineRunnerCapability, Vn as boolean, Vt as pickNativeLeaseOverride, Wn as literal, Yn as string, Zn as EventCategory, _t as failureContributionCapability, a as BackgroundRunRegistry, bn as errMsg, g as DEFAULT_DETAIL_CROP_CONVENTION, st as deriveDetailCropRect, y as DEFAULT_NATIVE_LEASE_SETTINGS, zn as _enum } from "../dist-Bpub2VcJ.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-BjCSgD4M.mjs";
|
|
3
|
+
import { _ as getStep, c as macroGateVerdict, d as isSessionDecodeReadGone, f as createSessionDecodeCoordinator, l as rootObjectGate, o as placeDetailStep, p as resolveFrameViewGeometry, r as CustomModelCatalog, s as stepsForElectedPool, u as localFrameRegistry, v as getStepDefinition } from "../default-detection-model-CMeVTcPZ.mjs";
|
|
4
4
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
6
6
|
import { c as withDetectionIntent, o as preRollRequestOf, t as DETECTION_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
|
|
@@ -896,10 +896,12 @@ function classifyNativeCropLeaseAge(ageMs, maxAgeMs = NATIVE_CROP_LEASE_MAX_AGE_
|
|
|
896
896
|
}
|
|
897
897
|
//#endregion
|
|
898
898
|
//#region src/session-decode/native-crop-registry.ts
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
899
|
+
/**
|
|
900
|
+
* Default max entries retained across all active decode sessions on a node
|
|
901
|
+
* (64 → 256 → 4096; see the class doc for the two windows the cap has been
|
|
902
|
+
* sized to).
|
|
903
|
+
*/
|
|
904
|
+
var DEFAULT_NATIVE_CROP_REGISTRY_CAP = 4096;
|
|
903
905
|
/** Invoke a requester's best-effort `release()`, swallowing any transport error. */
|
|
904
906
|
function safeRelease(request) {
|
|
905
907
|
try {
|
|
@@ -1166,20 +1168,6 @@ function createRetainedContentFallback(registry, ref) {
|
|
|
1166
1168
|
}
|
|
1167
1169
|
} };
|
|
1168
1170
|
}
|
|
1169
|
-
//#endregion
|
|
1170
|
-
//#region src/session-decode/parked-frame-store.ts
|
|
1171
|
-
/** Per-camera parcel bound. 24 live tracks × two kinds on one camera is a
|
|
1172
|
-
* crowd scene; past that the camera's oldest parcel leaves first. Read ONCE
|
|
1173
|
-
* from `CAMSTACK_PARKED_FRAMES_PER_DEVICE`. */
|
|
1174
|
-
var PARKED_FRAMES_PER_DEVICE_MAX = (() => {
|
|
1175
|
-
const raw = Number(process.env["CAMSTACK_PARKED_FRAMES_PER_DEVICE"]);
|
|
1176
|
-
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 48;
|
|
1177
|
-
})();
|
|
1178
|
-
/** {@link PARKED_FRAME_BUDGET_MB} in bytes. */
|
|
1179
|
-
var PARKED_FRAME_BUDGET_BYTES = (() => {
|
|
1180
|
-
const raw = Number(process.env["CAMSTACK_PARKED_FRAME_MB"]);
|
|
1181
|
-
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 64;
|
|
1182
|
-
})() * 1024 * 1024;
|
|
1183
1171
|
function keyOf$1(deviceId, trackId, kind) {
|
|
1184
1172
|
return `${deviceId}|${trackId}|${kind}`;
|
|
1185
1173
|
}
|
|
@@ -1196,8 +1184,8 @@ var ParkedFrameStore = class {
|
|
|
1196
1184
|
perDeviceKeys = /* @__PURE__ */ new Map();
|
|
1197
1185
|
totalBytes = 0;
|
|
1198
1186
|
constructor(options = {}) {
|
|
1199
|
-
this.budgetBytes = options.budgetBytes ??
|
|
1200
|
-
this.perDeviceMax = options.perDeviceMax ??
|
|
1187
|
+
this.budgetBytes = options.budgetBytes ?? 67108864;
|
|
1188
|
+
this.perDeviceMax = options.perDeviceMax ?? 48;
|
|
1201
1189
|
this.maxAgeMs = options.maxAgeMs ?? 6e5;
|
|
1202
1190
|
this.now = options.now ?? Date.now;
|
|
1203
1191
|
this.onEvict = options.onEvict;
|
|
@@ -1382,47 +1370,6 @@ var PartitionedParkedFrameStore = class {
|
|
|
1382
1370
|
this.faceSource.clear();
|
|
1383
1371
|
}
|
|
1384
1372
|
};
|
|
1385
|
-
/** {@link RETAINED_FRAME_BUDGET_MB} in bytes. */
|
|
1386
|
-
var RETAINED_FRAME_BUDGET_BYTES = (() => {
|
|
1387
|
-
const raw = Number(process.env["CAMSTACK_SESSION_RETAIN_MB"]);
|
|
1388
|
-
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 160;
|
|
1389
|
-
})() * 1024 * 1024;
|
|
1390
|
-
/**
|
|
1391
|
-
* How many of each device's MOST RECENT frames are protected from a busy
|
|
1392
|
-
* neighbour's budget eviction. Sized to cover the late two-plane / cross-process
|
|
1393
|
-
* enrichment horizon (~150-500 ms) at the REAL delivered rate: the store writes
|
|
1394
|
-
* every DELIVERED rgb frame, and a high-fps camera delivers ~25 fps (observed on
|
|
1395
|
-
* the 4K outdoor cams), so the old floor of 6 protected only ~240 ms there and
|
|
1396
|
-
* its late captures hit "frame recycled before resolve" (2026-07-22 triage —
|
|
1397
|
-
* missing thumbnails/firstFrames concentrated on exactly those cameras).
|
|
1398
|
-
* 16 frames ≈ 0.64 s @25 fps (1.6 s @10 fps). Only ACTIVE cameras hold frames,
|
|
1399
|
-
* so the worst-case protected footprint stays well inside the byte budget for
|
|
1400
|
-
* realistic concurrency (4 active cams ≈ 44 MB of 160); the hard ceiling always
|
|
1401
|
-
* overrides the floor regardless. Read ONCE from `CAMSTACK_SESSION_RETAIN_FLOOR`;
|
|
1402
|
-
* `0` disables the floor (pure global FIFO — the pre-2026-07-19 behaviour).
|
|
1403
|
-
*/
|
|
1404
|
-
var RETAINED_FRAME_PER_DEVICE_FLOOR = (() => {
|
|
1405
|
-
const raw = Number(process.env["CAMSTACK_SESSION_RETAIN_FLOOR"]);
|
|
1406
|
-
return Number.isFinite(raw) && raw >= 0 ? Math.floor(raw) : 16;
|
|
1407
|
-
})();
|
|
1408
|
-
/**
|
|
1409
|
-
* TIME-based per-device protection (2026-07-23 cold-window fix): a frame
|
|
1410
|
-
* YOUNGER than this survives budget eviction regardless of how many frames
|
|
1411
|
-
* its device holds. The COUNT floor above protects a fixed number of frames —
|
|
1412
|
-
* but the wall-clock window that buys depends on the delivered fps (16 frames
|
|
1413
|
-
* = 1.6 s @10 fps but only 0.64 s @25 fps, and the 4K street cams deliver
|
|
1414
|
-
* ~25). The late-capture horizon is TIME (session attach + enrichment +
|
|
1415
|
-
* round-trip ≈ 0.5–1.5 s, worst on cold on-motion dials), so the guarantee
|
|
1416
|
-
* must be time-denominated: 12/13 of the zero-media/missing-firstFrame tracks
|
|
1417
|
-
* in the 2026-07-23 audit were ≤6 s cold-session subjects whose handles were
|
|
1418
|
-
* recycled before their first captures ran. Bounded by the hard byte ceiling
|
|
1419
|
-
* (pass 2) exactly like the count floor — worst case ~26 MB per ACTIVE camera
|
|
1420
|
-
* @25 fps. `CAMSTACK_SESSION_RETAIN_FLOOR_MS`; `0` disables (count floor only).
|
|
1421
|
-
*/
|
|
1422
|
-
var RETAINED_FRAME_TIME_FLOOR_MS = (() => {
|
|
1423
|
-
const raw = Number(process.env["CAMSTACK_SESSION_RETAIN_FLOOR_MS"]);
|
|
1424
|
-
return Number.isFinite(raw) && raw >= 0 ? Math.floor(raw) : 3e3;
|
|
1425
|
-
})();
|
|
1426
1373
|
/** Opaque RAM-key prefix stamped into a retained frame's `FrameHandle.shmId`. */
|
|
1427
1374
|
var RETAINED_FRAME_KEY_PREFIX = "ram:";
|
|
1428
1375
|
/** A retention frame is uniquely identified by its key + slot + committed seq. */
|
|
@@ -1461,9 +1408,9 @@ var RetainedFrameStore = class RetainedFrameStore {
|
|
|
1461
1408
|
static SLOT_SPREAD = 1024;
|
|
1462
1409
|
constructor(options) {
|
|
1463
1410
|
this.nodeId = options.nodeId;
|
|
1464
|
-
this.budgetBytes = options.budgetBytes ??
|
|
1465
|
-
this.perDeviceFloor = options.perDeviceFloor ??
|
|
1466
|
-
this.timeFloorMs = options.timeFloorMs ??
|
|
1411
|
+
this.budgetBytes = options.budgetBytes ?? 167772160;
|
|
1412
|
+
this.perDeviceFloor = options.perDeviceFloor ?? 16;
|
|
1413
|
+
this.timeFloorMs = options.timeFloorMs ?? 3e3;
|
|
1467
1414
|
this.now = options.now ?? Date.now;
|
|
1468
1415
|
this.onEvict = options.onEvict;
|
|
1469
1416
|
}
|
|
@@ -2022,6 +1969,154 @@ function onboardRootDetections(slot, frame, gate) {
|
|
|
2022
1969
|
};
|
|
2023
1970
|
}
|
|
2024
1971
|
//#endregion
|
|
1972
|
+
//#region src/pipeline-runner/label-link.ts
|
|
1973
|
+
/**
|
|
1974
|
+
* The runner's half of the detector ↔ step label link (D715).
|
|
1975
|
+
*
|
|
1976
|
+
* The runner holds the camera's WHOLE step tree (the attach config), so it is
|
|
1977
|
+
* the one place that can answer "who writes this effect?" for a camera: the
|
|
1978
|
+
* root model's declaration (`fillsClassifierEffects`) against the filled
|
|
1979
|
+
* step's own `labelLink` policy and class list (`resolveLabelLink`). Three
|
|
1980
|
+
* consumers read that one answer:
|
|
1981
|
+
*
|
|
1982
|
+
* - the frame result — a linked label the executor wrote at score 0 is raised
|
|
1983
|
+
* to the detection's score when the detector is authoritative;
|
|
1984
|
+
* - the `detailSteps` announce — a skipped classifier is announced with
|
|
1985
|
+
* `filledBy`, so post-analysis does not dispatch it for a subject the
|
|
1986
|
+
* detector already named;
|
|
1987
|
+
* - `package-detection` — when the root fills it, the package root is not
|
|
1988
|
+
* dispatched at all and the root's own `package` boxes ARE the package
|
|
1989
|
+
* result (the operator's package threshold moves onto the root's gate, and
|
|
1990
|
+
* the frame says it looked).
|
|
1991
|
+
*
|
|
1992
|
+
* Pure: the caller passes the model resolver; no I/O, no clock.
|
|
1993
|
+
*/
|
|
1994
|
+
/** The root step the fills are read from — the always-on camera root. */
|
|
1995
|
+
var LABEL_LINK_ROOT_STEP_ID = "object-detection";
|
|
1996
|
+
var PACKAGE_STEP_ID = "package-detection";
|
|
1997
|
+
var PACKAGE_THRESHOLD_KEY = "minConfidencePackage";
|
|
1998
|
+
var EMPTY_LABEL_LINK_PLAN = { decisions: /* @__PURE__ */ new Map() };
|
|
1999
|
+
function findStep(steps, addonId) {
|
|
2000
|
+
for (const step of steps) {
|
|
2001
|
+
if (step.addonId === addonId) return step;
|
|
2002
|
+
const nested = step.children !== void 0 ? findStep(step.children, addonId) : void 0;
|
|
2003
|
+
if (nested !== void 0) return nested;
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* Plan a camera's label links from its configured tree. A root with no pinned
|
|
2008
|
+
* model runs the static default — a COCO model, which fills nothing.
|
|
2009
|
+
*/
|
|
2010
|
+
function planLabelLinks(steps, resolveModel) {
|
|
2011
|
+
if (steps === void 0) return EMPTY_LABEL_LINK_PLAN;
|
|
2012
|
+
const root = steps.find((s) => s.addonId === "object-detection" && s.enabled !== false);
|
|
2013
|
+
if (root?.modelId === void 0) return EMPTY_LABEL_LINK_PLAN;
|
|
2014
|
+
const fills = resolveModel("object-detection", root.modelId)?.fillsClassifierEffects ?? [];
|
|
2015
|
+
if (fills.length === 0) return {
|
|
2016
|
+
rootModelId: root.modelId,
|
|
2017
|
+
decisions: /* @__PURE__ */ new Map()
|
|
2018
|
+
};
|
|
2019
|
+
const decisions = /* @__PURE__ */ new Map();
|
|
2020
|
+
for (const fill of fills) {
|
|
2021
|
+
const step = findStep(steps, fill.stepId);
|
|
2022
|
+
decisions.set(fill.stepId, resolveLabelLink(fill, step === void 0 ? void 0 : {
|
|
2023
|
+
enabled: step.enabled !== false,
|
|
2024
|
+
...step.settings !== void 0 ? { settings: step.settings } : {}
|
|
2025
|
+
}));
|
|
2026
|
+
}
|
|
2027
|
+
return {
|
|
2028
|
+
rootModelId: root.modelId,
|
|
2029
|
+
decisions
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
/** Steps this plan says must not be dispatched, with the model that fills them. */
|
|
2033
|
+
function filledStepIds(plan) {
|
|
2034
|
+
const out = /* @__PURE__ */ new Map();
|
|
2035
|
+
if (plan.rootModelId === void 0) return out;
|
|
2036
|
+
for (const [stepId, decision] of plan.decisions) if (decision.skip) out.set(stepId, plan.rootModelId);
|
|
2037
|
+
return out;
|
|
2038
|
+
}
|
|
2039
|
+
function raiseLinkedLabels(detection, plan) {
|
|
2040
|
+
let changed = false;
|
|
2041
|
+
const labels = detection.labels.map((label) => {
|
|
2042
|
+
const stepId = linkedStepOf(label.stepId);
|
|
2043
|
+
if (stepId === void 0 || plan.decisions.get(stepId)?.authoritative !== true) return label;
|
|
2044
|
+
if (label.score === detection.score) return label;
|
|
2045
|
+
changed = true;
|
|
2046
|
+
return {
|
|
2047
|
+
...label,
|
|
2048
|
+
score: detection.score
|
|
2049
|
+
};
|
|
2050
|
+
});
|
|
2051
|
+
return changed ? labels : void 0;
|
|
2052
|
+
}
|
|
2053
|
+
/**
|
|
2054
|
+
* Raise each linked label to its detection's score where the detector is the
|
|
2055
|
+
* authoritative writer of that effect. Every other linked label stays the
|
|
2056
|
+
* score-0 fallback the executor wrote. Never mutates; returns the input when
|
|
2057
|
+
* nothing changes.
|
|
2058
|
+
*/
|
|
2059
|
+
function applyLabelLinkAuthority(result, plan) {
|
|
2060
|
+
if (plan.decisions.size === 0) return result;
|
|
2061
|
+
let changed = false;
|
|
2062
|
+
const detections = result.detections.map((d) => {
|
|
2063
|
+
const labels = raiseLinkedLabels(d, plan);
|
|
2064
|
+
if (labels === void 0) return d;
|
|
2065
|
+
changed = true;
|
|
2066
|
+
return {
|
|
2067
|
+
...d,
|
|
2068
|
+
labels
|
|
2069
|
+
};
|
|
2070
|
+
});
|
|
2071
|
+
return changed ? {
|
|
2072
|
+
...result,
|
|
2073
|
+
detections
|
|
2074
|
+
} : result;
|
|
2075
|
+
}
|
|
2076
|
+
/** The root step's schema default for its class allow-list. */
|
|
2077
|
+
function rootDefaultMacroClasses() {
|
|
2078
|
+
const field = getStep(LABEL_LINK_ROOT_STEP_ID).getConfigSchema().find((f) => "key" in f && f.key === "enabledMacroClasses");
|
|
2079
|
+
const value = field !== void 0 && "default" in field ? field.default : void 0;
|
|
2080
|
+
return Array.isArray(value) ? value : [];
|
|
2081
|
+
}
|
|
2082
|
+
function withPackageAdmitted(root, packageStep) {
|
|
2083
|
+
const settings = root.settings ?? {};
|
|
2084
|
+
const stored = settings["enabledMacroClasses"];
|
|
2085
|
+
const enabled = Array.isArray(stored) ? stored : rootDefaultMacroClasses();
|
|
2086
|
+
const admitted = enabled.length > 0 && !enabled.includes("package") ? { enabledMacroClasses: [...enabled, "package"] } : {};
|
|
2087
|
+
const threshold = packageStep.settings?.[PACKAGE_THRESHOLD_KEY];
|
|
2088
|
+
const gate = typeof threshold === "number" ? { [PACKAGE_THRESHOLD_KEY]: threshold } : {};
|
|
2089
|
+
return {
|
|
2090
|
+
...root,
|
|
2091
|
+
settings: {
|
|
2092
|
+
...settings,
|
|
2093
|
+
...admitted,
|
|
2094
|
+
...gate
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
/**
|
|
2099
|
+
* When the root fills `package-detection` and that step's policy lets it be
|
|
2100
|
+
* skipped, drop the package root from the dispatch and let the camera root
|
|
2101
|
+
* report packages: its gate admits `package` at the package step's threshold.
|
|
2102
|
+
* Otherwise the tree is returned untouched.
|
|
2103
|
+
*/
|
|
2104
|
+
function applyPackageFill(steps, plan) {
|
|
2105
|
+
if (plan.decisions.get(PACKAGE_STEP_ID)?.skip !== true) return {
|
|
2106
|
+
steps,
|
|
2107
|
+
filledByRoot: false
|
|
2108
|
+
};
|
|
2109
|
+
const packageStep = steps.find((s) => s.addonId === PACKAGE_STEP_ID);
|
|
2110
|
+
if (packageStep === void 0) return {
|
|
2111
|
+
steps,
|
|
2112
|
+
filledByRoot: false
|
|
2113
|
+
};
|
|
2114
|
+
return {
|
|
2115
|
+
steps: steps.filter((s) => s.addonId !== PACKAGE_STEP_ID).map((s) => s.addonId === "object-detection" && s.enabled !== false ? withPackageAdmitted(s, packageStep) : s),
|
|
2116
|
+
filledByRoot: true
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
//#endregion
|
|
2025
2120
|
//#region src/pipeline-runner/bench-step-schema.ts
|
|
2026
2121
|
/**
|
|
2027
2122
|
* Shared bench-facing schemas: the minimal recursive step tree. Extracted from
|
|
@@ -4537,9 +4632,9 @@ var PACKAGE_DETECTION_STEP_ID = "package-detection";
|
|
|
4537
4632
|
* through) and the frame was not shed. Post-analysis reads it as "an empty
|
|
4538
4633
|
* doormat on this frame is an ABSENCE, not silence" (D687). Never mutates.
|
|
4539
4634
|
*/
|
|
4540
|
-
function withPackageLook(result, dispatched) {
|
|
4635
|
+
function withPackageLook(result, dispatched, filledByRoot = false) {
|
|
4541
4636
|
if (result.shed === true) return result;
|
|
4542
|
-
return dispatched.some((s) => s.addonId === "package-detection" && s.enabled !== false) ? {
|
|
4637
|
+
return filledByRoot || dispatched.some((s) => s.addonId === "package-detection" && s.enabled !== false) ? {
|
|
4543
4638
|
...result,
|
|
4544
4639
|
packageLooked: true
|
|
4545
4640
|
} : result;
|
|
@@ -7239,20 +7334,23 @@ function isDetailPlaneStepId(stepId) {
|
|
|
7239
7334
|
* Extracted as a pure function so the unit suite can exercise the
|
|
7240
7335
|
* derivation without instantiating the full addon.
|
|
7241
7336
|
*/
|
|
7242
|
-
function deriveDetailSteps(steps) {
|
|
7337
|
+
function deriveDetailSteps(steps, plan = EMPTY_LABEL_LINK_PLAN) {
|
|
7243
7338
|
const stepIds = /* @__PURE__ */ new Set();
|
|
7244
7339
|
collectEnabledStepIds(steps, stepIds);
|
|
7340
|
+
const filled = filledStepIds(plan);
|
|
7245
7341
|
const announces = [];
|
|
7246
7342
|
for (const stepId of stepIds) {
|
|
7247
7343
|
const def = tryGetStepDefinition(stepId);
|
|
7248
7344
|
if (!def || def.inputClasses === null) continue;
|
|
7345
|
+
const filledBy = filled.get(def.id);
|
|
7249
7346
|
announces.push({
|
|
7250
7347
|
stepId: def.id,
|
|
7251
7348
|
inputClasses: def.inputClasses,
|
|
7252
7349
|
cadence: def.cadence ?? {
|
|
7253
7350
|
trigger: "once",
|
|
7254
7351
|
maxPerTrack: 3
|
|
7255
|
-
}
|
|
7352
|
+
},
|
|
7353
|
+
...filledBy !== void 0 ? { filledBy } : {}
|
|
7256
7354
|
});
|
|
7257
7355
|
}
|
|
7258
7356
|
return announces;
|
|
@@ -9568,6 +9666,42 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
9568
9666
|
* read synchronously by the placement.
|
|
9569
9667
|
*/
|
|
9570
9668
|
customModels = new CustomModelCatalog({ warn: (message, extras) => this.ctxIfReady?.logger.warn(message, extras) });
|
|
9669
|
+
/**
|
|
9670
|
+
* Per camera, the label-link plan (D715) and the announce derived from it,
|
|
9671
|
+
* keyed on the two inputs it reads: the attach tree and the custom-model
|
|
9672
|
+
* snapshot (a Frigate+ root is a custom model). Recomputed when either
|
|
9673
|
+
* changes identity — at most once per catalog refresh.
|
|
9674
|
+
*/
|
|
9675
|
+
labelLinkCache = /* @__PURE__ */ new Map();
|
|
9676
|
+
/** The camera's label-link plan; logs once per change of what is filled. */
|
|
9677
|
+
labelLinkPlanFor(deviceId, steps) {
|
|
9678
|
+
const byStep = this.customModels.current();
|
|
9679
|
+
const cached = this.labelLinkCache.get(deviceId);
|
|
9680
|
+
if (cached !== void 0 && cached.steps === steps && cached.byStep === byStep) return cached.plan;
|
|
9681
|
+
const plan = planLabelLinks(steps, (stepId, modelId) => this.customModels.stepDefinition(stepId)?.models.find((m) => m.id === modelId));
|
|
9682
|
+
const announces = deriveDetailSteps(steps, plan);
|
|
9683
|
+
this.labelLinkCache.set(deviceId, {
|
|
9684
|
+
steps,
|
|
9685
|
+
byStep,
|
|
9686
|
+
plan,
|
|
9687
|
+
announces
|
|
9688
|
+
});
|
|
9689
|
+
const describe = (p) => p === void 0 ? "" : [...p.decisions].map(([id, d]) => `${id}:${d.skip ? "skip" : d.authoritative ? "sole" : "fallback"}`).join(",");
|
|
9690
|
+
if (describe(cached?.plan) !== describe(plan) && plan.decisions.size > 0) this.ctxIfReady?.logger.info("label link: the root model fills pipeline steps", {
|
|
9691
|
+
tags: { deviceId },
|
|
9692
|
+
meta: {
|
|
9693
|
+
rootModelId: plan.rootModelId ?? null,
|
|
9694
|
+
steps: [...plan.decisions].map(([stepId, d]) => ({
|
|
9695
|
+
stepId,
|
|
9696
|
+
policy: d.policy,
|
|
9697
|
+
authoritative: d.authoritative,
|
|
9698
|
+
skip: d.skip,
|
|
9699
|
+
openGaps: d.openGaps
|
|
9700
|
+
}))
|
|
9701
|
+
}
|
|
9702
|
+
});
|
|
9703
|
+
return plan;
|
|
9704
|
+
}
|
|
9571
9705
|
cropConvention = new CropConventionSource({ logger: {
|
|
9572
9706
|
info: (message, extras) => this.ctxIfReady?.logger.info(message, extras),
|
|
9573
9707
|
warn: (message, extras) => this.ctxIfReady?.logger.warn(message, extras)
|
|
@@ -9963,6 +10097,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
9963
10097
|
this.lastDecodeUnexpectedEndAt.delete(deviceId);
|
|
9964
10098
|
this.packageGovernor.forget(deviceId);
|
|
9965
10099
|
this.packageGateSkips.delete(deviceId);
|
|
10100
|
+
this.labelLinkCache.delete(deviceId);
|
|
9966
10101
|
this.packageZoneUnionByDevice.delete(deviceId);
|
|
9967
10102
|
this.packageZoneUnionAt.delete(deviceId);
|
|
9968
10103
|
this.lastMotionNearPackageZone.delete(deviceId);
|
|
@@ -10359,7 +10494,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
10359
10494
|
acquire: () => this.acquireSessionDecodeRestream(api, config.deviceId, config.detectionStreamId, `session-decode:detect:${config.deviceId}`, resolveSessionDecodeHostname(config, process.env["CAMSTACK_HUB_URL"]), resolveSessionDecodeOwnerNodeId(config), true),
|
|
10360
10495
|
startPump: (source, hooks) => {
|
|
10361
10496
|
const dialMs = Date.now() - requestedAt;
|
|
10362
|
-
const useLocalFrameRef = this.executorCoLocated()
|
|
10497
|
+
const useLocalFrameRef = this.executorCoLocated();
|
|
10363
10498
|
log.info("session-decode: detection routed through per-session decode worker (rgb)", { meta: {
|
|
10364
10499
|
streamId: config.detectionStreamId,
|
|
10365
10500
|
codec: source.codec,
|
|
@@ -10678,8 +10813,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
10678
10813
|
return null;
|
|
10679
10814
|
}
|
|
10680
10815
|
if (steps.length === 0) return null;
|
|
10681
|
-
|
|
10682
|
-
|
|
10816
|
+
const labelLinkPlan = this.labelLinkPlanFor(deviceId, steps);
|
|
10817
|
+
const packageFill = applyPackageFill(steps, labelLinkPlan);
|
|
10818
|
+
let dispatchSteps = packageFill.steps;
|
|
10819
|
+
if (dispatchSteps.some((s) => s.addonId === "package-detection" && s.enabled !== false)) {
|
|
10683
10820
|
this.refreshPackageZoneUnion(deviceId);
|
|
10684
10821
|
const motionInZone = this.lastMotionNearPackageZone.get(deviceId) ?? this.lastAnalyzerDetected.get(deviceId) ?? false;
|
|
10685
10822
|
const decision = this.packageGovernor.evaluate({
|
|
@@ -10689,7 +10826,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
10689
10826
|
});
|
|
10690
10827
|
const skipped = this.packageGateSkips.get(deviceId) ?? 0;
|
|
10691
10828
|
if (!decision.run) {
|
|
10692
|
-
dispatchSteps =
|
|
10829
|
+
dispatchSteps = dispatchSteps.filter((s) => s.addonId !== PACKAGE_DETECTION_STEP_ID);
|
|
10693
10830
|
if (skipped === 0) log.info("package-detection gated off by the motion-settle governor", {
|
|
10694
10831
|
tags: { deviceId },
|
|
10695
10832
|
meta: { motionInZone: this.lastAnalyzerDetected.get(deviceId) ?? false }
|
|
@@ -10766,7 +10903,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
10766
10903
|
return null;
|
|
10767
10904
|
}
|
|
10768
10905
|
if (result === null) return null;
|
|
10769
|
-
const looked = withPackageLook(result, dispatchSteps);
|
|
10906
|
+
const looked = withPackageLook(applyLabelLinkAuthority(result, labelLinkPlan), dispatchSteps, packageFill.filledByRoot);
|
|
10770
10907
|
return this.recoverSmallSubjects(deviceId, frame, looked, dispatchSteps, camConfig?.deviceKey);
|
|
10771
10908
|
}
|
|
10772
10909
|
/**
|
|
@@ -11413,7 +11550,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
11413
11550
|
...this.liveWorkerSlotWaiter(deviceId),
|
|
11414
11551
|
acquire: () => this.acquireSessionDecodeRestream(api, config.deviceId, config.detectionStreamId, `session-decode:occupancy:${config.deviceId}`, resolveSessionDecodeHostname(config, process.env["CAMSTACK_HUB_URL"]), resolveSessionDecodeOwnerNodeId(config)),
|
|
11415
11552
|
startPump: (source, hooks) => {
|
|
11416
|
-
const useLocalFrameRef = this.executorCoLocated()
|
|
11553
|
+
const useLocalFrameRef = this.executorCoLocated();
|
|
11417
11554
|
return startSessionDecodePump({
|
|
11418
11555
|
fork: this.forkDecodeWorkerWithLease,
|
|
11419
11556
|
lease: this.resolveSessionLeaseKnobs,
|
|
@@ -11463,7 +11600,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
11463
11600
|
emitInferenceResult(deviceId, frame, result, handle, source, occasion) {
|
|
11464
11601
|
if (!this.ctx?.eventBus) return;
|
|
11465
11602
|
const capturedAt = frame.capturedAt;
|
|
11466
|
-
const detailSteps = this.attached.get(deviceId)?.detailSteps;
|
|
11603
|
+
const detailSteps = this.labelLinkCache.get(deviceId)?.announces ?? this.attached.get(deviceId)?.detailSteps;
|
|
11467
11604
|
const payload = {
|
|
11468
11605
|
deviceId,
|
|
11469
11606
|
frame: result,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-wJO7mXeO.js");
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
node_fs = require_chunk.__toESM(node_fs);
|
|
5
5
|
let node_child_process = require("node:child_process");
|
package/dist/recorder/index.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
6
|
+
const require_dist = require("../dist-wJO7mXeO.js");
|
|
7
|
+
const require_node = require("../node-BCrqaejt.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
9
|
const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
|
|
10
10
|
const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $t as
|
|
2
|
-
import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
1
|
+
import { $t as resolveLocationMode, An as hydrateSchema, B as RECORDING_SOURCE_CAMSTACK_ADDON, Bn as array, Dn as customAction, Dt as loadContributionCapability, Ft as modeMayWrite, G as VISIT_MERGE_GAP_MS, Gn as number, Gt as recordingArchiveCapability, H as RecordingSignalStatusSchema, Jn as record, Jt as recordingSignalCapability, Kn as object, Kt as recordingCapability, Ln as selectAssignedProfileSlots, Mt as mayWriteToLocation, Nt as memoizePinnedFfmpeg, On as defineCustomActions, P as OpsLogEntrySchema, Pn as nodePin, Pt as migrateLegacyDeviceSignalConfig, R as RECORDING_EXPORT_MAX_READ_BYTES, Rn as sleep$1, S as EVENT_PAD_MS, Sn as BaseAddon, V as RecordingConfigSchema, Vn as boolean, W as VIDEOCLIPS_MAX_OFFER_BYTES, Xt as resolveCreateExportSubject, Yn as string, Z as batteryCapability, Zn as EventCategory, _ as DEFAULT_EVENTS_BAND_BUFFER_SEC, an as storageOccupancyCapability, bn as errMsg$1, ct as deriveRecordingMode, et as clipExportFailure, gt as exportSubjectOf, hn as evaluateSensorEdge, ht as evictionPolicyOfLocation, in as storageEvictableCapability, jt as mayReadLocation, ln as videoclipsCapability, mt as evictionPolicyForMode, o as BatteryStatusSchema, ot as deriveBatteryPresence, qn as preprocess, qt as recordingExportCapability, s as CLIP_BROKER_PACED_RATES, sn as stripRetiredBandPreBufferSec, tn as resolveRecordingProfiles, tt as clipExportFailureOf, vn as DeviceFeature, w as ExportRecordSchema, wt as isFirstLevelMacroClass, x as EVENT_OWNER_TYPES, yn as DeviceType, yt as gbToBytes, z as RECORDING_SOURCE_CAMSTACK, zn as _enum } from "../dist-Bpub2VcJ.mjs";
|
|
2
|
+
import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-BjCSgD4M.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
4
|
import { d as PREBUFFER_MAX_MS, l as withRecordingIntent, r as RECORDING_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
|
|
5
5
|
import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { bn as errMsg } from "./dist-Bpub2VcJ.mjs";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
//#region src/stream-broker/recorded/avcc-annexb.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-wJO7mXeO.js");
|
|
3
3
|
let node_child_process = require("node:child_process");
|
|
4
4
|
//#region src/stream-broker/recorded/avcc-annexb.ts
|
|
5
5
|
/**
|
|
@@ -1494,7 +1494,7 @@ function resolvePlanarCropSource(kind, planes, strides, region) {
|
|
|
1494
1494
|
//#region src/session-decode/pinned-rgb-crop.ts
|
|
1495
1495
|
/**
|
|
1496
1496
|
* Pure decision/plumbing helpers for the `pinnedRgbCrop` native-crop color fix
|
|
1497
|
-
* (
|
|
1497
|
+
* (always on since 2026-07-20 — see `decode-worker-child.ts`).
|
|
1498
1498
|
*
|
|
1499
1499
|
* ## The bug this fixes
|
|
1500
1500
|
*
|
|
@@ -2292,14 +2292,10 @@ var NATIVE_TILE_JPEG_QUALITY = 90;
|
|
|
2292
2292
|
* 500 ms deliberately, not more: the confirmation gate bounds each crop attempt
|
|
2293
2293
|
* at 300 ms and the capture scheduler drops an enrichment request older than
|
|
2294
2294
|
* 3 s, so a miss held too long stops being a fast retryable `null` and becomes
|
|
2295
|
-
* an upstream timeout.
|
|
2296
|
-
*
|
|
2297
|
-
* is; `0` disables the wait and restores the pre-2026-09-07 miss profile.
|
|
2295
|
+
* an upstream timeout. Change it only once `cutLatencyMs` on the metrics line
|
|
2296
|
+
* says what the encode window really is.
|
|
2298
2297
|
*/
|
|
2299
|
-
var TILE_CUT_WAIT_MS =
|
|
2300
|
-
const raw = Number(process.env["CAMSTACK_SESSION_TILE_CUT_WAIT_MS"]);
|
|
2301
|
-
return Number.isFinite(raw) && raw >= 0 ? Math.floor(raw) : 500;
|
|
2302
|
-
})();
|
|
2298
|
+
var TILE_CUT_WAIT_MS = 500;
|
|
2303
2299
|
/** How many early-withdrawn frame ids the worker remembers for the miss line. */
|
|
2304
2300
|
var UNMARKED_MEMORY = 256;
|
|
2305
2301
|
/**
|
|
@@ -2322,8 +2318,8 @@ var UNMARKED_MEMORY = 256;
|
|
|
2322
2318
|
var LEASE_DOWNLOAD_COOLDOWN_BASE_MS = 6e4;
|
|
2323
2319
|
var LEASE_DOWNLOAD_COOLDOWN_MAX_MS = 6e5;
|
|
2324
2320
|
/**
|
|
2325
|
-
*
|
|
2326
|
-
*
|
|
2321
|
+
* Pinned-color RGB24 native-crop retention — the only lease download since the
|
|
2322
|
+
* 2026-07-20 rollout (its opt-out env was removed on 2026-10-06).
|
|
2327
2323
|
*
|
|
2328
2324
|
* ## What it fixes
|
|
2329
2325
|
* On a HARDWARE session the full-frame download pins its YUV→RGB conversion to
|
|
@@ -2336,7 +2332,7 @@ var LEASE_DOWNLOAD_COOLDOWN_MAX_MS = 6e5;
|
|
|
2336
2332
|
* crop (CPU-sws default) can resolve DIFFERENTLY → the crop gets a wrong hue /
|
|
2337
2333
|
* desaturation while the full frame looks right.
|
|
2338
2334
|
*
|
|
2339
|
-
* ## What it does
|
|
2335
|
+
* ## What it does
|
|
2340
2336
|
* The HW→system lease download converts to RGB24 ONCE, pinned to the SAME
|
|
2341
2337
|
* resolved color the full-frame path uses (see {@link buildLeaseDownloadDescription});
|
|
2342
2338
|
* the later crop is then a pure SPATIAL RGB24→RGB24 crop + resize with no color
|
|
@@ -2349,7 +2345,6 @@ var LEASE_DOWNLOAD_COOLDOWN_MAX_MS = 6e5;
|
|
|
2349
2345
|
* software-DEGRADE path is left on YUV420P (its full frame + crop both use the
|
|
2350
2346
|
* CPU-sws default, so there is no mismatch to fix there).
|
|
2351
2347
|
*/
|
|
2352
|
-
var PINNED_RGB_CROP = process.env["CAMSTACK_SESSION_PINNED_RGB_CROP"] !== "0";
|
|
2353
2348
|
/**
|
|
2354
2349
|
* The libav GPU scale filter for a hwaccel backend, or `null` when none is
|
|
2355
2350
|
* known here — those backends fall back to the software crop+scale path.
|
|
@@ -2803,8 +2798,6 @@ var DecodeWorkerChild = class {
|
|
|
2803
2798
|
* 2026-07-23) — each emit differs from the previous one and every frame logs
|
|
2804
2799
|
* as a "TRANSITION", flooding the log ring (~40 lines/s per camera). */
|
|
2805
2800
|
lastColorProvenanceKeyByPath = /* @__PURE__ */ new Map();
|
|
2806
|
-
/** Per-frame color provenance logging (opt-in; the transition marker is always on). */
|
|
2807
|
-
colorDebug = process.env["CAMSTACK_DECODE_COLOR_DEBUG"] === "1";
|
|
2808
2801
|
/** Throughput counters (plain integers, no per-frame allocation). */
|
|
2809
2802
|
framesDecoded = 0;
|
|
2810
2803
|
/** Releases that found a held frame / that found nothing to release. */
|
|
@@ -3516,14 +3509,13 @@ var DecodeWorkerChild = class {
|
|
|
3516
3509
|
* Emit the color-provenance marker: which decode/scale path produced this
|
|
3517
3510
|
* frame + its raw and resolved source color. Always logs on a TRANSITION (the
|
|
3518
3511
|
* path or the frame's raw color tags changed vs the last emit — rare, and the
|
|
3519
|
-
* exact signal a desaturation recurrence leaves)
|
|
3520
|
-
* the `CAMSTACK_DECODE_COLOR_DEBUG` flag.
|
|
3512
|
+
* exact signal a desaturation recurrence leaves).
|
|
3521
3513
|
*/
|
|
3522
3514
|
logColorProvenance(path, color) {
|
|
3523
3515
|
const key = `${color.rawColorSpace}|${color.rawColorRange}`;
|
|
3524
3516
|
const transition = this.lastColorProvenanceKeyByPath.get(path) !== key;
|
|
3525
3517
|
if (transition) this.lastColorProvenanceKeyByPath.set(path, key);
|
|
3526
|
-
if (transition
|
|
3518
|
+
if (transition) this.emitStderr(colorProvenanceLine(path, color, transition));
|
|
3527
3519
|
}
|
|
3528
3520
|
/**
|
|
3529
3521
|
* Retain a just-superseded DELIVERED frame for later native crops. Transfers
|
|
@@ -3582,7 +3574,7 @@ var DecodeWorkerChild = class {
|
|
|
3582
3574
|
* ## What it costs / saves
|
|
3583
3575
|
*
|
|
3584
3576
|
* One 4K frame is ~24.9 MB on the default pinned-RGB24 lease path
|
|
3585
|
-
* (
|
|
3577
|
+
* (pinned RGB24), ~12.4 MB as YUV420P. At the ~25 delivered fps of
|
|
3586
3578
|
* `all` mode that is ~620 MB/s of GPU→RAM download while the gate is open and
|
|
3587
3579
|
* a steady-state resident set of roughly `frameBytes × deliveredFps ×
|
|
3588
3580
|
* ttlSeconds`. `inferred` cuts both by the governor's admit ratio — ~5 of 25
|
|
@@ -3651,7 +3643,7 @@ var DecodeWorkerChild = class {
|
|
|
3651
3643
|
this.settlePreRoll(frameId, "download-failed");
|
|
3652
3644
|
return true;
|
|
3653
3645
|
}
|
|
3654
|
-
this.leaseStore.put(frameId,
|
|
3646
|
+
this.leaseStore.put(frameId, toLeasedRgbNavFrame(software));
|
|
3655
3647
|
return true;
|
|
3656
3648
|
}
|
|
3657
3649
|
this.leaseStore.put(frameId, toLeasedNavFrame(frame));
|
|
@@ -3668,8 +3660,8 @@ var DecodeWorkerChild = class {
|
|
|
3668
3660
|
const scaleFilter = this.gpuScaleFilter;
|
|
3669
3661
|
if (!nav || !scaleFilter || !this.hwContext) return null;
|
|
3670
3662
|
try {
|
|
3671
|
-
const color =
|
|
3672
|
-
|
|
3663
|
+
const color = this.resolveFrameColor(frame);
|
|
3664
|
+
this.logColorProvenance("hw-crop", color);
|
|
3673
3665
|
const outputs = this.ensureLeaseDownloadFilter(nav, scaleFilter, frame.width, frame.height, color).processAllSync(frame);
|
|
3674
3666
|
const first = outputs[0] ?? null;
|
|
3675
3667
|
for (let i = 1; i < outputs.length; i++) outputs[i]?.free();
|