@camstack/addon-pipeline 1.1.70 → 1.2.0
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 +181 -469
- package/dist/detection-pipeline/index.mjs +182 -469
- package/dist/{dist-CurVt3xC.mjs → dist-DLWXeXC1.mjs} +239 -60
- package/dist/{dist-BWn5k0A5.js → dist-DWy-H6bo.js} +250 -59
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +24 -2
- package/dist/pipeline-runner/index.mjs +24 -2
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/session-decode/decode-worker-child.js +177 -12
- package/dist/session-decode/decode-worker-child.mjs +177 -12
- package/dist/{step-definitions-B7e8rPe3.js → step-definitions-BQG_6dmZ.js} +6 -2
- package/dist/{step-definitions-BKm17nce.mjs → step-definitions-CVk19Y0u.mjs} +6 -2
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-yAAGMET5.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CpB1jG0N.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BflyNuZv.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-5Zc9wj-A.mjs +26 -0
- package/dist/stream-broker/{hostInit-DUzRsTmt.mjs → hostInit--Zair8Av.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/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-D6bWMuew.js → MaskShapeCanvas-DI4BY7W2-sOOxiGvP.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-C-1enV21.js → MotionZonesSettings-NcxxQN8r-DdTQuT23.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-By9pdGP7.js → PrivacyMaskSettings-APgPLF7p-BrR0L3ql.js} +1 -1
- package/embed-dist/assets/index-D4MGuECB.css +2 -0
- package/embed-dist/assets/{index-BPGh79kn.js → index-Dk21l1_3.js} +14 -14
- package/embed-dist/index.html +2 -2
- 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-D68Lj69v.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-CDBALHSV.mjs +0 -26
- package/embed-dist/assets/index-D2pF9Z3W.css +0 -2
|
@@ -517,6 +517,87 @@ var NativeLeaseStore = class {
|
|
|
517
517
|
}
|
|
518
518
|
};
|
|
519
519
|
//#endregion
|
|
520
|
+
//#region src/session-decode/pinned-rgb-crop.ts
|
|
521
|
+
/**
|
|
522
|
+
* Pure decision/plumbing helpers for the `pinnedRgbCrop` native-crop color fix
|
|
523
|
+
* (DEFAULT OFF — see `CAMSTACK_SESSION_PINNED_RGB_CROP` in `decode-worker-child.ts`).
|
|
524
|
+
*
|
|
525
|
+
* ## The bug this fixes
|
|
526
|
+
*
|
|
527
|
+
* On a HARDWARE decode session the FULL-frame download pins its YUV→RGB
|
|
528
|
+
* conversion to the resolved `(matrix, range)` on the GPU filtergraph
|
|
529
|
+
* (`buildGpuFilterDescription` → `colorConvertFilterOptions`). The native-CROP
|
|
530
|
+
* survival path, however, retains the frame as **YUV420P** and later converts
|
|
531
|
+
* it to RGB with a CPU `SoftwareScaleContext` that node-av exposes NO
|
|
532
|
+
* colorspace-pinning surface for — so it falls back to libswscale's own default
|
|
533
|
+
* coefficients. When the stream carries NO color-matrix metadata
|
|
534
|
+
* (`colorSpace = UNSPECIFIED`, e.g. cam 617), the full frame (pinned bt709/
|
|
535
|
+
* limited via {@link resolveSourceColor}'s defaults) and the crop (CPU-sws
|
|
536
|
+
* default) can resolve DIFFERENTLY → the crop gets a wrong hue / desaturation
|
|
537
|
+
* while the full frame looks right.
|
|
538
|
+
*
|
|
539
|
+
* ## The fix (retain-once-in-pinned-RGB)
|
|
540
|
+
*
|
|
541
|
+
* When the flag is on, the HW→system lease download converts to RGB24 ONCE,
|
|
542
|
+
* pinned to the SAME resolved `(matrix, range)` the full-frame path uses. The
|
|
543
|
+
* later crop is then a pure SPATIAL RGB24→RGB24 crop + resize with NO color
|
|
544
|
+
* math, so it cannot re-resolve color differently than the full frame.
|
|
545
|
+
*
|
|
546
|
+
* These helpers are the PURE decision surface (filter description, cache keys,
|
|
547
|
+
* RAM-budget size) so the plumbing is unit-testable without node-av / ffmpeg.
|
|
548
|
+
* The software-DEGRADE path stays YUV420P (its full frame + crop both use the
|
|
549
|
+
* CPU-sws default, so there is no mismatch to fix there).
|
|
550
|
+
*/
|
|
551
|
+
/**
|
|
552
|
+
* The full-frame GPU→system download filtergraph description.
|
|
553
|
+
*
|
|
554
|
+
* - `color === null` (flag OFF / legacy): download to YUV420P, NO color convert
|
|
555
|
+
* — byte-for-byte the historical `scale=w=iw:h=ih,hwdownload,format=nv12,format=yuv420p`.
|
|
556
|
+
* - `color !== null` (flag ON): pin the SAME resolved src matrix/range + full-
|
|
557
|
+
* range RGB output the full-frame path pins, converting to rgb24 in one pass.
|
|
558
|
+
*/
|
|
559
|
+
function buildLeaseDownloadDescription(scaleFilter, color) {
|
|
560
|
+
if (color) return `${scaleFilter}=w=iw:h=ih,hwdownload,format=nv12,scale=${colorConvertFilterOptions(color)},format=rgb24`;
|
|
561
|
+
return `${scaleFilter}=w=iw:h=ih,hwdownload,format=nv12,format=yuv420p`;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Cache key for the lease-download filtergraph. Flag OFF returns the historical
|
|
565
|
+
* `${srcW}x${srcH}` key byte-for-byte; flag ON folds the resolved color in so a
|
|
566
|
+
* mid-session colorspace/range change rebuilds the pinned-convert graph instead
|
|
567
|
+
* of reusing one pinned to the old color.
|
|
568
|
+
*/
|
|
569
|
+
function leaseDownloadFilterKey(srcW, srcH, color) {
|
|
570
|
+
return color ? `${srcW}x${srcH}:rgb:${sourceColorKey(color)}` : `${srcW}x${srcH}`;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Cache key for the dedicated native-crop software scaler. YUV420P (flag OFF /
|
|
574
|
+
* degrade) returns the historical `${srcW}x${srcH}->${dstW}x${dstH}` key
|
|
575
|
+
* byte-for-byte; the RGB24 (flag ON) scaler carries an `rgb:` prefix so an RGB
|
|
576
|
+
* scaler and a YUV scaler of identical geometry never alias the same cache slot.
|
|
577
|
+
*/
|
|
578
|
+
function nativeCropScalerKey(srcW, srcH, dstW, dstH, rgb24) {
|
|
579
|
+
const base = `${srcW}x${srcH}->${dstW}x${dstH}`;
|
|
580
|
+
return rgb24 ? `rgb:${base}` : base;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Approximate resident bytes of a retained software frame, for the lease
|
|
584
|
+
* RAM-budget tally. RGB24 packs 3 bytes/px (~2x YUV420P's 1.5) — the documented
|
|
585
|
+
* cost of pinned-RGB retention.
|
|
586
|
+
*/
|
|
587
|
+
function retainedFrameBytes(width, height, rgb24) {
|
|
588
|
+
return rgb24 ? width * height * 3 : Math.ceil(width * height * 1.5);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Byte offset into a PACKED RGB24 plane for a crop origin — the pure spatial
|
|
592
|
+
* math the `pinnedRgbCrop` crop uses to zero-copy view the ROI. Packed RGB24 is
|
|
593
|
+
* a single plane at 3 bytes/px with NO chroma subsampling, so the offset is a
|
|
594
|
+
* plain `top*stride + left*3` — no half-plane arithmetic and, critically, no
|
|
595
|
+
* color conversion (that already happened, pinned, at download time).
|
|
596
|
+
*/
|
|
597
|
+
function rgbCropSourceOffset(top, left, stride) {
|
|
598
|
+
return top * stride + left * 3;
|
|
599
|
+
}
|
|
600
|
+
//#endregion
|
|
520
601
|
//#region src/session-decode/decode-worker-child.ts
|
|
521
602
|
/**
|
|
522
603
|
* Decode-worker CHILD entry point — Epic C P1, Task 2.
|
|
@@ -546,7 +627,19 @@ var NativeLeaseStore = class {
|
|
|
546
627
|
function toLeasedNavFrame(frame) {
|
|
547
628
|
return {
|
|
548
629
|
frame,
|
|
549
|
-
byteLength:
|
|
630
|
+
byteLength: retainedFrameBytes(frame.width, frame.height, false),
|
|
631
|
+
free: () => frame.free()
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Wrap a software RGB24 frame as a lease entry (byte size = w×h×3) — the
|
|
636
|
+
* `pinnedRgbCrop` path. Kept separate from {@link toLeasedNavFrame} so the
|
|
637
|
+
* flag-off YUV420P wrap is untouched.
|
|
638
|
+
*/
|
|
639
|
+
function toLeasedRgbNavFrame(frame) {
|
|
640
|
+
return {
|
|
641
|
+
frame,
|
|
642
|
+
byteLength: retainedFrameBytes(frame.width, frame.height, true),
|
|
550
643
|
free: () => frame.free()
|
|
551
644
|
};
|
|
552
645
|
}
|
|
@@ -611,6 +704,35 @@ var NATIVE_LEASE_ACTIVITY_WINDOW_MS = (() => {
|
|
|
611
704
|
return Number.isFinite(raw) && raw >= 0 ? Math.floor(raw) : 15e3;
|
|
612
705
|
})();
|
|
613
706
|
/**
|
|
707
|
+
* `pinnedRgbCrop` — pinned-color RGB24 native-crop retention. DEFAULT **ON**
|
|
708
|
+
* (2026-07-20 rollout); set `CAMSTACK_SESSION_PINNED_RGB_CROP=0` to opt out.
|
|
709
|
+
*
|
|
710
|
+
* ## What it fixes
|
|
711
|
+
* On a HARDWARE session the full-frame download pins its YUV→RGB conversion to
|
|
712
|
+
* the resolved `(matrix, range)` on the GPU filtergraph, but the native-CROP
|
|
713
|
+
* lease path retains the frame as YUV420P and later converts it with a CPU
|
|
714
|
+
* `SoftwareScaleContext` that node-av gives NO colorspace-pinning surface for —
|
|
715
|
+
* so the crop falls back to libswscale's default coefficients. On a stream with
|
|
716
|
+
* NO color-matrix metadata (`colorSpace = UNSPECIFIED`, e.g. cam 617) the full
|
|
717
|
+
* frame (pinned bt709/limited by {@link resolveSourceColor}'s defaults) and the
|
|
718
|
+
* crop (CPU-sws default) can resolve DIFFERENTLY → the crop gets a wrong hue /
|
|
719
|
+
* desaturation while the full frame looks right.
|
|
720
|
+
*
|
|
721
|
+
* ## What it does when ON
|
|
722
|
+
* The HW→system lease download converts to RGB24 ONCE, pinned to the SAME
|
|
723
|
+
* resolved color the full-frame path uses (see {@link buildLeaseDownloadDescription});
|
|
724
|
+
* the later crop is then a pure SPATIAL RGB24→RGB24 crop + resize with no color
|
|
725
|
+
* math (see {@link nativeScaleCropToBuffer}'s RGB branch), so it cannot diverge.
|
|
726
|
+
*
|
|
727
|
+
* ## Cost
|
|
728
|
+
* A retained RGB24 frame is ~2x the RAM of YUV420P (3 vs 1.5 bytes/px — ~6.2 vs
|
|
729
|
+
* ~3.1 MB per 1080p frame). Retention stays DEMAND-GATED by {@link leaseGate},
|
|
730
|
+
* so cameras nothing is cropping retain nothing regardless of this flag. The
|
|
731
|
+
* software-DEGRADE path is left on YUV420P (its full frame + crop both use the
|
|
732
|
+
* CPU-sws default, so there is no mismatch to fix there).
|
|
733
|
+
*/
|
|
734
|
+
var PINNED_RGB_CROP = process.env["CAMSTACK_SESSION_PINNED_RGB_CROP"] !== "0";
|
|
735
|
+
/**
|
|
614
736
|
* The libav GPU scale filter for a hwaccel backend, or `null` when none is
|
|
615
737
|
* known here — those backends fall back to the software crop+scale path.
|
|
616
738
|
* Mirrors `addon-decoder-ffmpeg/src/ffmpeg-args.ts` `gpuScaleFilterForBackend`.
|
|
@@ -1148,7 +1270,7 @@ var DecodeWorkerChild = class {
|
|
|
1148
1270
|
const software = this.downloadToSoftware(frame);
|
|
1149
1271
|
frame.free();
|
|
1150
1272
|
if (!software) return true;
|
|
1151
|
-
this.leaseStore.put(frameId, toLeasedNavFrame(software));
|
|
1273
|
+
this.leaseStore.put(frameId, PINNED_RGB_CROP ? toLeasedRgbNavFrame(software) : toLeasedNavFrame(software));
|
|
1152
1274
|
return true;
|
|
1153
1275
|
}
|
|
1154
1276
|
this.leaseStore.put(frameId, toLeasedNavFrame(frame));
|
|
@@ -1165,7 +1287,9 @@ var DecodeWorkerChild = class {
|
|
|
1165
1287
|
const scaleFilter = this.gpuScaleFilter;
|
|
1166
1288
|
if (!nav || !scaleFilter || !this.hwContext) return null;
|
|
1167
1289
|
try {
|
|
1168
|
-
const
|
|
1290
|
+
const color = PINNED_RGB_CROP ? this.resolveFrameColor(frame) : null;
|
|
1291
|
+
if (color) this.logColorProvenance("hw-crop", color);
|
|
1292
|
+
const outputs = this.ensureLeaseDownloadFilter(nav, scaleFilter, frame.width, frame.height, color).processAllSync(frame);
|
|
1169
1293
|
const first = outputs[0] ?? null;
|
|
1170
1294
|
for (let i = 1; i < outputs.length; i++) outputs[i]?.free();
|
|
1171
1295
|
return first;
|
|
@@ -1179,9 +1303,17 @@ var DecodeWorkerChild = class {
|
|
|
1179
1303
|
return null;
|
|
1180
1304
|
}
|
|
1181
1305
|
}
|
|
1182
|
-
/**
|
|
1183
|
-
|
|
1184
|
-
|
|
1306
|
+
/**
|
|
1307
|
+
* Build-once / reuse the full-frame GPU→system download filtergraph.
|
|
1308
|
+
*
|
|
1309
|
+
* - `color === null` (flag OFF): YUV420P download, byte-for-byte the historical
|
|
1310
|
+
* `scale=w=iw:h=ih,hwdownload,format=nv12,format=yuv420p` + `${srcW}x${srcH}` key.
|
|
1311
|
+
* - `color !== null` (flag ON): pinned-color RGB24 download; the resolved color
|
|
1312
|
+
* is folded into the cache key so a mid-session colorspace/range change
|
|
1313
|
+
* rebuilds the graph instead of reusing one pinned to the old color.
|
|
1314
|
+
*/
|
|
1315
|
+
ensureLeaseDownloadFilter(nav, scaleFilter, srcW, srcH, color) {
|
|
1316
|
+
const key = leaseDownloadFilterKey(srcW, srcH, color);
|
|
1185
1317
|
const cached = this.nativeLeaseDownloadFilter;
|
|
1186
1318
|
if (cached && key === this.nativeLeaseDownloadFilterKey) {
|
|
1187
1319
|
this.leaseDownloadFilterUses++;
|
|
@@ -1190,7 +1322,7 @@ var DecodeWorkerChild = class {
|
|
|
1190
1322
|
this.nativeLeaseDownloadFilter?.close();
|
|
1191
1323
|
this.nativeLeaseDownloadFilter = null;
|
|
1192
1324
|
this.nativeLeaseDownloadFilterKey = "";
|
|
1193
|
-
const description =
|
|
1325
|
+
const description = buildLeaseDownloadDescription(scaleFilter, color);
|
|
1194
1326
|
const filter = nav.FilterAPI.create(description, { hardware: this.hwContext });
|
|
1195
1327
|
this.nativeLeaseDownloadFilter = filter;
|
|
1196
1328
|
this.nativeLeaseDownloadFilterKey = key;
|
|
@@ -1212,6 +1344,7 @@ var DecodeWorkerChild = class {
|
|
|
1212
1344
|
const nav = this.nav;
|
|
1213
1345
|
const C = this.consts;
|
|
1214
1346
|
if (!nav || !C) throw new Error("node-av not initialized");
|
|
1347
|
+
if (frame.format === C.AV_PIX_FMT_RGB24) return this.nativeRgbCropToBuffer(nav, C, frame, resolved);
|
|
1215
1348
|
this.logColorProvenance("sw-crop", this.resolveFrameColor(frame));
|
|
1216
1349
|
const { region, target } = resolved;
|
|
1217
1350
|
const planes = frame.data;
|
|
@@ -1225,7 +1358,7 @@ var DecodeWorkerChild = class {
|
|
|
1225
1358
|
const ySlice = yPlane.subarray(region.top * yStride + region.left);
|
|
1226
1359
|
const uSlice = uPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
1227
1360
|
const vSlice = vPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
1228
|
-
const scaler = this.ensureNativeCropScaler(nav, C, region.width, region.height, target.width, target.height);
|
|
1361
|
+
const scaler = this.ensureNativeCropScaler(nav, C, region.width, region.height, target.width, target.height, C.AV_PIX_FMT_YUV420P);
|
|
1229
1362
|
const tightStride = target.width * 3;
|
|
1230
1363
|
const dstStride = tightStride + 63 & -64;
|
|
1231
1364
|
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height + 64);
|
|
@@ -1244,6 +1377,31 @@ var DecodeWorkerChild = class {
|
|
|
1244
1377
|
return packSinglePlane(dstBuffer, dstStride, target.width, target.height, 3);
|
|
1245
1378
|
}
|
|
1246
1379
|
/**
|
|
1380
|
+
* `pinnedRgbCrop` software crop — the retained frame is ALREADY pinned
|
|
1381
|
+
* full-range RGB24 (color resolved once at download), so this is a pure
|
|
1382
|
+
* SPATIAL crop + RGB→RGB resize: offset the single packed plane to the crop
|
|
1383
|
+
* origin (zero-copy) and scale ONLY the ROI. NO color math, NO YUV planes, NO
|
|
1384
|
+
* provenance marker (the conversion happened + was logged at download time).
|
|
1385
|
+
* Mirrors {@link nativeScaleCropToBuffer}'s stride-alignment + tail-slack
|
|
1386
|
+
* discipline exactly (same SIMD-overshoot heap-corruption guard).
|
|
1387
|
+
*/
|
|
1388
|
+
nativeRgbCropToBuffer(nav, C, frame, resolved) {
|
|
1389
|
+
const { region, target } = resolved;
|
|
1390
|
+
const plane = frame.data?.[0];
|
|
1391
|
+
if (!plane) throw new Error("decode-worker-child: retained RGB frame missing packed plane data");
|
|
1392
|
+
const srcStride = frame.linesize[0] ?? 0;
|
|
1393
|
+
const srcSlice = plane.subarray(rgbCropSourceOffset(region.top, region.left, srcStride));
|
|
1394
|
+
const scaler = this.ensureNativeCropScaler(nav, C, region.width, region.height, target.width, target.height, C.AV_PIX_FMT_RGB24);
|
|
1395
|
+
const tightStride = target.width * 3;
|
|
1396
|
+
const dstStride = tightStride + 63 & -64;
|
|
1397
|
+
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height + 64);
|
|
1398
|
+
const scaledHeight = scaler.scaleSync([srcSlice], [srcStride], 0, region.height, [dstBuffer], [dstStride]);
|
|
1399
|
+
if (scaledHeight < 0) throw new Error(`native rgb crop sws_scale failed: ${scaledHeight}`);
|
|
1400
|
+
if (scaledHeight !== target.height) throw new Error(`native rgb crop scaler produced ${scaledHeight} of ${target.height} rows`);
|
|
1401
|
+
if (dstStride === tightStride) return dstBuffer.subarray(0, tightStride * target.height);
|
|
1402
|
+
return packSinglePlane(dstBuffer, dstStride, target.width, target.height, 3);
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1247
1405
|
* Hardware native crop — run the retained GPU surface through a DEDICATED
|
|
1248
1406
|
* crop filtergraph (`hwdownload,format=nv12,crop=…,scale=…,format=rgb24`) and
|
|
1249
1407
|
* pack the small result. Mirrors {@link hwScaleToBuffer} but uses its OWN
|
|
@@ -1267,16 +1425,23 @@ var DecodeWorkerChild = class {
|
|
|
1267
1425
|
for (const out of outputs) out.free();
|
|
1268
1426
|
}
|
|
1269
1427
|
}
|
|
1270
|
-
/**
|
|
1271
|
-
|
|
1272
|
-
|
|
1428
|
+
/**
|
|
1429
|
+
* Build-once / reuse the dedicated native-crop software scaler (rgb out).
|
|
1430
|
+
* `srcFmt` parameterizes the SOURCE pixel format so the scaler matches the
|
|
1431
|
+
* retained frame: `AV_PIX_FMT_YUV420P` (flag OFF / degrade — YUV→RGB convert)
|
|
1432
|
+
* or `AV_PIX_FMT_RGB24` (`pinnedRgbCrop` — a pure RGB→RGB spatial resize). The
|
|
1433
|
+
* cache key folds the format in so an RGB and a YUV scaler of identical
|
|
1434
|
+
* geometry never alias one slot (see {@link nativeCropScalerKey}).
|
|
1435
|
+
*/
|
|
1436
|
+
ensureNativeCropScaler(nav, C, srcW, srcH, dstW, dstH, srcFmt) {
|
|
1437
|
+
const key = nativeCropScalerKey(srcW, srcH, dstW, dstH, srcFmt === C.AV_PIX_FMT_RGB24);
|
|
1273
1438
|
const cached = this.nativeCropScaler;
|
|
1274
1439
|
if (cached && key === this.nativeCropScalerKey) return cached;
|
|
1275
1440
|
this.nativeCropScaler?.[Symbol.dispose]?.();
|
|
1276
1441
|
this.nativeCropScaler = null;
|
|
1277
1442
|
this.nativeCropScalerKey = "";
|
|
1278
1443
|
const scaler = new nav.SoftwareScaleContext();
|
|
1279
|
-
scaler.getContext(srcW, srcH,
|
|
1444
|
+
scaler.getContext(srcW, srcH, srcFmt, dstW, dstH, C.AV_PIX_FMT_RGB24, C.SWS_FAST_BILINEAR);
|
|
1280
1445
|
const initRet = scaler.initContext();
|
|
1281
1446
|
if (initRet < 0) {
|
|
1282
1447
|
scaler[Symbol.dispose]?.();
|
|
@@ -513,6 +513,87 @@ var NativeLeaseStore = class {
|
|
|
513
513
|
}
|
|
514
514
|
};
|
|
515
515
|
//#endregion
|
|
516
|
+
//#region src/session-decode/pinned-rgb-crop.ts
|
|
517
|
+
/**
|
|
518
|
+
* Pure decision/plumbing helpers for the `pinnedRgbCrop` native-crop color fix
|
|
519
|
+
* (DEFAULT OFF — see `CAMSTACK_SESSION_PINNED_RGB_CROP` in `decode-worker-child.ts`).
|
|
520
|
+
*
|
|
521
|
+
* ## The bug this fixes
|
|
522
|
+
*
|
|
523
|
+
* On a HARDWARE decode session the FULL-frame download pins its YUV→RGB
|
|
524
|
+
* conversion to the resolved `(matrix, range)` on the GPU filtergraph
|
|
525
|
+
* (`buildGpuFilterDescription` → `colorConvertFilterOptions`). The native-CROP
|
|
526
|
+
* survival path, however, retains the frame as **YUV420P** and later converts
|
|
527
|
+
* it to RGB with a CPU `SoftwareScaleContext` that node-av exposes NO
|
|
528
|
+
* colorspace-pinning surface for — so it falls back to libswscale's own default
|
|
529
|
+
* coefficients. When the stream carries NO color-matrix metadata
|
|
530
|
+
* (`colorSpace = UNSPECIFIED`, e.g. cam 617), the full frame (pinned bt709/
|
|
531
|
+
* limited via {@link resolveSourceColor}'s defaults) and the crop (CPU-sws
|
|
532
|
+
* default) can resolve DIFFERENTLY → the crop gets a wrong hue / desaturation
|
|
533
|
+
* while the full frame looks right.
|
|
534
|
+
*
|
|
535
|
+
* ## The fix (retain-once-in-pinned-RGB)
|
|
536
|
+
*
|
|
537
|
+
* When the flag is on, the HW→system lease download converts to RGB24 ONCE,
|
|
538
|
+
* pinned to the SAME resolved `(matrix, range)` the full-frame path uses. The
|
|
539
|
+
* later crop is then a pure SPATIAL RGB24→RGB24 crop + resize with NO color
|
|
540
|
+
* math, so it cannot re-resolve color differently than the full frame.
|
|
541
|
+
*
|
|
542
|
+
* These helpers are the PURE decision surface (filter description, cache keys,
|
|
543
|
+
* RAM-budget size) so the plumbing is unit-testable without node-av / ffmpeg.
|
|
544
|
+
* The software-DEGRADE path stays YUV420P (its full frame + crop both use the
|
|
545
|
+
* CPU-sws default, so there is no mismatch to fix there).
|
|
546
|
+
*/
|
|
547
|
+
/**
|
|
548
|
+
* The full-frame GPU→system download filtergraph description.
|
|
549
|
+
*
|
|
550
|
+
* - `color === null` (flag OFF / legacy): download to YUV420P, NO color convert
|
|
551
|
+
* — byte-for-byte the historical `scale=w=iw:h=ih,hwdownload,format=nv12,format=yuv420p`.
|
|
552
|
+
* - `color !== null` (flag ON): pin the SAME resolved src matrix/range + full-
|
|
553
|
+
* range RGB output the full-frame path pins, converting to rgb24 in one pass.
|
|
554
|
+
*/
|
|
555
|
+
function buildLeaseDownloadDescription(scaleFilter, color) {
|
|
556
|
+
if (color) return `${scaleFilter}=w=iw:h=ih,hwdownload,format=nv12,scale=${colorConvertFilterOptions(color)},format=rgb24`;
|
|
557
|
+
return `${scaleFilter}=w=iw:h=ih,hwdownload,format=nv12,format=yuv420p`;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Cache key for the lease-download filtergraph. Flag OFF returns the historical
|
|
561
|
+
* `${srcW}x${srcH}` key byte-for-byte; flag ON folds the resolved color in so a
|
|
562
|
+
* mid-session colorspace/range change rebuilds the pinned-convert graph instead
|
|
563
|
+
* of reusing one pinned to the old color.
|
|
564
|
+
*/
|
|
565
|
+
function leaseDownloadFilterKey(srcW, srcH, color) {
|
|
566
|
+
return color ? `${srcW}x${srcH}:rgb:${sourceColorKey(color)}` : `${srcW}x${srcH}`;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Cache key for the dedicated native-crop software scaler. YUV420P (flag OFF /
|
|
570
|
+
* degrade) returns the historical `${srcW}x${srcH}->${dstW}x${dstH}` key
|
|
571
|
+
* byte-for-byte; the RGB24 (flag ON) scaler carries an `rgb:` prefix so an RGB
|
|
572
|
+
* scaler and a YUV scaler of identical geometry never alias the same cache slot.
|
|
573
|
+
*/
|
|
574
|
+
function nativeCropScalerKey(srcW, srcH, dstW, dstH, rgb24) {
|
|
575
|
+
const base = `${srcW}x${srcH}->${dstW}x${dstH}`;
|
|
576
|
+
return rgb24 ? `rgb:${base}` : base;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Approximate resident bytes of a retained software frame, for the lease
|
|
580
|
+
* RAM-budget tally. RGB24 packs 3 bytes/px (~2x YUV420P's 1.5) — the documented
|
|
581
|
+
* cost of pinned-RGB retention.
|
|
582
|
+
*/
|
|
583
|
+
function retainedFrameBytes(width, height, rgb24) {
|
|
584
|
+
return rgb24 ? width * height * 3 : Math.ceil(width * height * 1.5);
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Byte offset into a PACKED RGB24 plane for a crop origin — the pure spatial
|
|
588
|
+
* math the `pinnedRgbCrop` crop uses to zero-copy view the ROI. Packed RGB24 is
|
|
589
|
+
* a single plane at 3 bytes/px with NO chroma subsampling, so the offset is a
|
|
590
|
+
* plain `top*stride + left*3` — no half-plane arithmetic and, critically, no
|
|
591
|
+
* color conversion (that already happened, pinned, at download time).
|
|
592
|
+
*/
|
|
593
|
+
function rgbCropSourceOffset(top, left, stride) {
|
|
594
|
+
return top * stride + left * 3;
|
|
595
|
+
}
|
|
596
|
+
//#endregion
|
|
516
597
|
//#region src/session-decode/decode-worker-child.ts
|
|
517
598
|
/**
|
|
518
599
|
* Decode-worker CHILD entry point — Epic C P1, Task 2.
|
|
@@ -542,7 +623,19 @@ var NativeLeaseStore = class {
|
|
|
542
623
|
function toLeasedNavFrame(frame) {
|
|
543
624
|
return {
|
|
544
625
|
frame,
|
|
545
|
-
byteLength:
|
|
626
|
+
byteLength: retainedFrameBytes(frame.width, frame.height, false),
|
|
627
|
+
free: () => frame.free()
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Wrap a software RGB24 frame as a lease entry (byte size = w×h×3) — the
|
|
632
|
+
* `pinnedRgbCrop` path. Kept separate from {@link toLeasedNavFrame} so the
|
|
633
|
+
* flag-off YUV420P wrap is untouched.
|
|
634
|
+
*/
|
|
635
|
+
function toLeasedRgbNavFrame(frame) {
|
|
636
|
+
return {
|
|
637
|
+
frame,
|
|
638
|
+
byteLength: retainedFrameBytes(frame.width, frame.height, true),
|
|
546
639
|
free: () => frame.free()
|
|
547
640
|
};
|
|
548
641
|
}
|
|
@@ -607,6 +700,35 @@ var NATIVE_LEASE_ACTIVITY_WINDOW_MS = (() => {
|
|
|
607
700
|
return Number.isFinite(raw) && raw >= 0 ? Math.floor(raw) : 15e3;
|
|
608
701
|
})();
|
|
609
702
|
/**
|
|
703
|
+
* `pinnedRgbCrop` — pinned-color RGB24 native-crop retention. DEFAULT **ON**
|
|
704
|
+
* (2026-07-20 rollout); set `CAMSTACK_SESSION_PINNED_RGB_CROP=0` to opt out.
|
|
705
|
+
*
|
|
706
|
+
* ## What it fixes
|
|
707
|
+
* On a HARDWARE session the full-frame download pins its YUV→RGB conversion to
|
|
708
|
+
* the resolved `(matrix, range)` on the GPU filtergraph, but the native-CROP
|
|
709
|
+
* lease path retains the frame as YUV420P and later converts it with a CPU
|
|
710
|
+
* `SoftwareScaleContext` that node-av gives NO colorspace-pinning surface for —
|
|
711
|
+
* so the crop falls back to libswscale's default coefficients. On a stream with
|
|
712
|
+
* NO color-matrix metadata (`colorSpace = UNSPECIFIED`, e.g. cam 617) the full
|
|
713
|
+
* frame (pinned bt709/limited by {@link resolveSourceColor}'s defaults) and the
|
|
714
|
+
* crop (CPU-sws default) can resolve DIFFERENTLY → the crop gets a wrong hue /
|
|
715
|
+
* desaturation while the full frame looks right.
|
|
716
|
+
*
|
|
717
|
+
* ## What it does when ON
|
|
718
|
+
* The HW→system lease download converts to RGB24 ONCE, pinned to the SAME
|
|
719
|
+
* resolved color the full-frame path uses (see {@link buildLeaseDownloadDescription});
|
|
720
|
+
* the later crop is then a pure SPATIAL RGB24→RGB24 crop + resize with no color
|
|
721
|
+
* math (see {@link nativeScaleCropToBuffer}'s RGB branch), so it cannot diverge.
|
|
722
|
+
*
|
|
723
|
+
* ## Cost
|
|
724
|
+
* A retained RGB24 frame is ~2x the RAM of YUV420P (3 vs 1.5 bytes/px — ~6.2 vs
|
|
725
|
+
* ~3.1 MB per 1080p frame). Retention stays DEMAND-GATED by {@link leaseGate},
|
|
726
|
+
* so cameras nothing is cropping retain nothing regardless of this flag. The
|
|
727
|
+
* software-DEGRADE path is left on YUV420P (its full frame + crop both use the
|
|
728
|
+
* CPU-sws default, so there is no mismatch to fix there).
|
|
729
|
+
*/
|
|
730
|
+
var PINNED_RGB_CROP = process.env["CAMSTACK_SESSION_PINNED_RGB_CROP"] !== "0";
|
|
731
|
+
/**
|
|
610
732
|
* The libav GPU scale filter for a hwaccel backend, or `null` when none is
|
|
611
733
|
* known here — those backends fall back to the software crop+scale path.
|
|
612
734
|
* Mirrors `addon-decoder-ffmpeg/src/ffmpeg-args.ts` `gpuScaleFilterForBackend`.
|
|
@@ -1144,7 +1266,7 @@ var DecodeWorkerChild = class {
|
|
|
1144
1266
|
const software = this.downloadToSoftware(frame);
|
|
1145
1267
|
frame.free();
|
|
1146
1268
|
if (!software) return true;
|
|
1147
|
-
this.leaseStore.put(frameId, toLeasedNavFrame(software));
|
|
1269
|
+
this.leaseStore.put(frameId, PINNED_RGB_CROP ? toLeasedRgbNavFrame(software) : toLeasedNavFrame(software));
|
|
1148
1270
|
return true;
|
|
1149
1271
|
}
|
|
1150
1272
|
this.leaseStore.put(frameId, toLeasedNavFrame(frame));
|
|
@@ -1161,7 +1283,9 @@ var DecodeWorkerChild = class {
|
|
|
1161
1283
|
const scaleFilter = this.gpuScaleFilter;
|
|
1162
1284
|
if (!nav || !scaleFilter || !this.hwContext) return null;
|
|
1163
1285
|
try {
|
|
1164
|
-
const
|
|
1286
|
+
const color = PINNED_RGB_CROP ? this.resolveFrameColor(frame) : null;
|
|
1287
|
+
if (color) this.logColorProvenance("hw-crop", color);
|
|
1288
|
+
const outputs = this.ensureLeaseDownloadFilter(nav, scaleFilter, frame.width, frame.height, color).processAllSync(frame);
|
|
1165
1289
|
const first = outputs[0] ?? null;
|
|
1166
1290
|
for (let i = 1; i < outputs.length; i++) outputs[i]?.free();
|
|
1167
1291
|
return first;
|
|
@@ -1175,9 +1299,17 @@ var DecodeWorkerChild = class {
|
|
|
1175
1299
|
return null;
|
|
1176
1300
|
}
|
|
1177
1301
|
}
|
|
1178
|
-
/**
|
|
1179
|
-
|
|
1180
|
-
|
|
1302
|
+
/**
|
|
1303
|
+
* Build-once / reuse the full-frame GPU→system download filtergraph.
|
|
1304
|
+
*
|
|
1305
|
+
* - `color === null` (flag OFF): YUV420P download, byte-for-byte the historical
|
|
1306
|
+
* `scale=w=iw:h=ih,hwdownload,format=nv12,format=yuv420p` + `${srcW}x${srcH}` key.
|
|
1307
|
+
* - `color !== null` (flag ON): pinned-color RGB24 download; the resolved color
|
|
1308
|
+
* is folded into the cache key so a mid-session colorspace/range change
|
|
1309
|
+
* rebuilds the graph instead of reusing one pinned to the old color.
|
|
1310
|
+
*/
|
|
1311
|
+
ensureLeaseDownloadFilter(nav, scaleFilter, srcW, srcH, color) {
|
|
1312
|
+
const key = leaseDownloadFilterKey(srcW, srcH, color);
|
|
1181
1313
|
const cached = this.nativeLeaseDownloadFilter;
|
|
1182
1314
|
if (cached && key === this.nativeLeaseDownloadFilterKey) {
|
|
1183
1315
|
this.leaseDownloadFilterUses++;
|
|
@@ -1186,7 +1318,7 @@ var DecodeWorkerChild = class {
|
|
|
1186
1318
|
this.nativeLeaseDownloadFilter?.close();
|
|
1187
1319
|
this.nativeLeaseDownloadFilter = null;
|
|
1188
1320
|
this.nativeLeaseDownloadFilterKey = "";
|
|
1189
|
-
const description =
|
|
1321
|
+
const description = buildLeaseDownloadDescription(scaleFilter, color);
|
|
1190
1322
|
const filter = nav.FilterAPI.create(description, { hardware: this.hwContext });
|
|
1191
1323
|
this.nativeLeaseDownloadFilter = filter;
|
|
1192
1324
|
this.nativeLeaseDownloadFilterKey = key;
|
|
@@ -1208,6 +1340,7 @@ var DecodeWorkerChild = class {
|
|
|
1208
1340
|
const nav = this.nav;
|
|
1209
1341
|
const C = this.consts;
|
|
1210
1342
|
if (!nav || !C) throw new Error("node-av not initialized");
|
|
1343
|
+
if (frame.format === C.AV_PIX_FMT_RGB24) return this.nativeRgbCropToBuffer(nav, C, frame, resolved);
|
|
1211
1344
|
this.logColorProvenance("sw-crop", this.resolveFrameColor(frame));
|
|
1212
1345
|
const { region, target } = resolved;
|
|
1213
1346
|
const planes = frame.data;
|
|
@@ -1221,7 +1354,7 @@ var DecodeWorkerChild = class {
|
|
|
1221
1354
|
const ySlice = yPlane.subarray(region.top * yStride + region.left);
|
|
1222
1355
|
const uSlice = uPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
1223
1356
|
const vSlice = vPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
1224
|
-
const scaler = this.ensureNativeCropScaler(nav, C, region.width, region.height, target.width, target.height);
|
|
1357
|
+
const scaler = this.ensureNativeCropScaler(nav, C, region.width, region.height, target.width, target.height, C.AV_PIX_FMT_YUV420P);
|
|
1225
1358
|
const tightStride = target.width * 3;
|
|
1226
1359
|
const dstStride = tightStride + 63 & -64;
|
|
1227
1360
|
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height + 64);
|
|
@@ -1240,6 +1373,31 @@ var DecodeWorkerChild = class {
|
|
|
1240
1373
|
return packSinglePlane(dstBuffer, dstStride, target.width, target.height, 3);
|
|
1241
1374
|
}
|
|
1242
1375
|
/**
|
|
1376
|
+
* `pinnedRgbCrop` software crop — the retained frame is ALREADY pinned
|
|
1377
|
+
* full-range RGB24 (color resolved once at download), so this is a pure
|
|
1378
|
+
* SPATIAL crop + RGB→RGB resize: offset the single packed plane to the crop
|
|
1379
|
+
* origin (zero-copy) and scale ONLY the ROI. NO color math, NO YUV planes, NO
|
|
1380
|
+
* provenance marker (the conversion happened + was logged at download time).
|
|
1381
|
+
* Mirrors {@link nativeScaleCropToBuffer}'s stride-alignment + tail-slack
|
|
1382
|
+
* discipline exactly (same SIMD-overshoot heap-corruption guard).
|
|
1383
|
+
*/
|
|
1384
|
+
nativeRgbCropToBuffer(nav, C, frame, resolved) {
|
|
1385
|
+
const { region, target } = resolved;
|
|
1386
|
+
const plane = frame.data?.[0];
|
|
1387
|
+
if (!plane) throw new Error("decode-worker-child: retained RGB frame missing packed plane data");
|
|
1388
|
+
const srcStride = frame.linesize[0] ?? 0;
|
|
1389
|
+
const srcSlice = plane.subarray(rgbCropSourceOffset(region.top, region.left, srcStride));
|
|
1390
|
+
const scaler = this.ensureNativeCropScaler(nav, C, region.width, region.height, target.width, target.height, C.AV_PIX_FMT_RGB24);
|
|
1391
|
+
const tightStride = target.width * 3;
|
|
1392
|
+
const dstStride = tightStride + 63 & -64;
|
|
1393
|
+
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height + 64);
|
|
1394
|
+
const scaledHeight = scaler.scaleSync([srcSlice], [srcStride], 0, region.height, [dstBuffer], [dstStride]);
|
|
1395
|
+
if (scaledHeight < 0) throw new Error(`native rgb crop sws_scale failed: ${scaledHeight}`);
|
|
1396
|
+
if (scaledHeight !== target.height) throw new Error(`native rgb crop scaler produced ${scaledHeight} of ${target.height} rows`);
|
|
1397
|
+
if (dstStride === tightStride) return dstBuffer.subarray(0, tightStride * target.height);
|
|
1398
|
+
return packSinglePlane(dstBuffer, dstStride, target.width, target.height, 3);
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1243
1401
|
* Hardware native crop — run the retained GPU surface through a DEDICATED
|
|
1244
1402
|
* crop filtergraph (`hwdownload,format=nv12,crop=…,scale=…,format=rgb24`) and
|
|
1245
1403
|
* pack the small result. Mirrors {@link hwScaleToBuffer} but uses its OWN
|
|
@@ -1263,16 +1421,23 @@ var DecodeWorkerChild = class {
|
|
|
1263
1421
|
for (const out of outputs) out.free();
|
|
1264
1422
|
}
|
|
1265
1423
|
}
|
|
1266
|
-
/**
|
|
1267
|
-
|
|
1268
|
-
|
|
1424
|
+
/**
|
|
1425
|
+
* Build-once / reuse the dedicated native-crop software scaler (rgb out).
|
|
1426
|
+
* `srcFmt` parameterizes the SOURCE pixel format so the scaler matches the
|
|
1427
|
+
* retained frame: `AV_PIX_FMT_YUV420P` (flag OFF / degrade — YUV→RGB convert)
|
|
1428
|
+
* or `AV_PIX_FMT_RGB24` (`pinnedRgbCrop` — a pure RGB→RGB spatial resize). The
|
|
1429
|
+
* cache key folds the format in so an RGB and a YUV scaler of identical
|
|
1430
|
+
* geometry never alias one slot (see {@link nativeCropScalerKey}).
|
|
1431
|
+
*/
|
|
1432
|
+
ensureNativeCropScaler(nav, C, srcW, srcH, dstW, dstH, srcFmt) {
|
|
1433
|
+
const key = nativeCropScalerKey(srcW, srcH, dstW, dstH, srcFmt === C.AV_PIX_FMT_RGB24);
|
|
1269
1434
|
const cached = this.nativeCropScaler;
|
|
1270
1435
|
if (cached && key === this.nativeCropScalerKey) return cached;
|
|
1271
1436
|
this.nativeCropScaler?.[Symbol.dispose]?.();
|
|
1272
1437
|
this.nativeCropScaler = null;
|
|
1273
1438
|
this.nativeCropScalerKey = "";
|
|
1274
1439
|
const scaler = new nav.SoftwareScaleContext();
|
|
1275
|
-
scaler.getContext(srcW, srcH,
|
|
1440
|
+
scaler.getContext(srcW, srcH, srcFmt, dstW, dstH, C.AV_PIX_FMT_RGB24, C.SWS_FAST_BILINEAR);
|
|
1276
1441
|
const initRet = scaler.initContext();
|
|
1277
1442
|
if (initRet < 0) {
|
|
1278
1443
|
scaler[Symbol.dispose]?.();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_dist = require("./dist-DWy-H6bo.js");
|
|
2
2
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
3
3
|
var HF_REPO = "camstack/camstack-models";
|
|
4
4
|
var HF_SCRYPTED = "scrypted/plugin-models";
|
|
@@ -1273,7 +1273,11 @@ var ObjectDetectionStep = class {
|
|
|
1273
1273
|
max: 1,
|
|
1274
1274
|
step: .05,
|
|
1275
1275
|
default: .5,
|
|
1276
|
-
showValue: true
|
|
1276
|
+
showValue: true,
|
|
1277
|
+
showWhen: {
|
|
1278
|
+
field: "enabledMacroClasses",
|
|
1279
|
+
includes: "package"
|
|
1280
|
+
}
|
|
1277
1281
|
},
|
|
1278
1282
|
{
|
|
1279
1283
|
type: "slider",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS
|
|
1
|
+
import { E as hfModelUrl, a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS } from "./dist-DLWXeXC1.mjs";
|
|
2
2
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
3
3
|
var HF_REPO = "camstack/camstack-models";
|
|
4
4
|
var HF_SCRYPTED = "scrypted/plugin-models";
|
|
@@ -1273,7 +1273,11 @@ var ObjectDetectionStep = class {
|
|
|
1273
1273
|
max: 1,
|
|
1274
1274
|
step: .05,
|
|
1275
1275
|
default: .5,
|
|
1276
|
-
showValue: true
|
|
1276
|
+
showValue: true,
|
|
1277
|
+
showWhen: {
|
|
1278
|
+
field: "enabledMacroClasses",
|
|
1279
|
+
includes: "package"
|
|
1280
|
+
}
|
|
1277
1281
|
},
|
|
1278
1282
|
{
|
|
1279
1283
|
type: "slider",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as e, c as t, d as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-
|
|
1
|
+
import { a as e, c as t, d as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-5Zc9wj-A.mjs";
|
|
2
2
|
import { a as d, i as f, n as p, o as m, r as h, t as g } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs";
|
|
3
3
|
import { n as _, r as v, t as y } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs";
|
|
4
4
|
import { n as b, t as x } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs";
|
|
5
|
-
import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
5
|
+
import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BflyNuZv.mjs";
|
|
6
6
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils.js
|
|
7
7
|
var C = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), w = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), T = (e) => {
|
|
8
8
|
let t = w(e);
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.2.0",
|
|
7
7
|
scope: ["default"],
|
|
8
8
|
loaded: !1,
|
|
9
9
|
from: "addon_stream_broker_widgets",
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.
|
|
21
|
+
version: "1.2.0",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_stream_broker_widgets",
|
|
@@ -33,7 +33,7 @@ var e = {
|
|
|
33
33
|
},
|
|
34
34
|
"@camstack/ui-library": {
|
|
35
35
|
name: "@camstack/ui-library",
|
|
36
|
-
version: "1.
|
|
36
|
+
version: "1.2.0",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_stream_broker_widgets",
|