@camstack/addon-pipeline 1.2.368 → 1.2.370
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 +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-BY-aEI2s.js → custom-model-catalog-BFosahFu.js} +2 -2
- package/dist/{custom-model-catalog-Bnel86hH.mjs → custom-model-catalog-CVbK0xKc.mjs} +2 -2
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-5AhGOWWu.mjs → dist-CbFPOFAD.mjs} +407 -14
- package/dist/{dist-DDXsZaRH.js → dist-jkwxbcbK.js} +407 -14
- package/dist/{model-catalogs-DWR9EsGI.mjs → model-catalogs-DJmwfLfC.mjs} +1 -1
- package/dist/{model-catalogs-DJN58c_U.js → model-catalogs-Ds2hC2Br.js} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-DqZJFOzR.mjs → node-C-2fB9kH.mjs} +1 -1
- package/dist/{node-CiciZWts.js → node-C_1U1uzn.js} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-Batknjjt.mjs → process-memory-B3I-NvnX.mjs} +1 -1
- package/dist/{process-memory-BRu19Dgr.js → process-memory-Cfh1BQYg.js} +1 -1
- package/dist/recorder/index.js +12 -2
- package/dist/recorder/index.mjs +12 -2
- package/dist/{segment-demux-js-dlhO3Q8W.mjs → segment-demux-js-D3JBJeN6.mjs} +1 -1
- package/dist/{segment-demux-js-0CRf7GAb.js → segment-demux-js-uxBcJy15.js} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CSajlHKC.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DwwDKaZJ.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Bna0L8uC.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-BAvXcDKy.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-KJ1eka58.mjs → hostInit-DVwYY7oo.mjs} +2 -2
- package/dist/stream-broker/index.js +302 -90
- package/dist/stream-broker/index.mjs +302 -90
- package/dist/stream-broker/remoteEntry.js +1 -1
- 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-BfVREmhg.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-5KL24-a_.mjs +0 -26
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { $n as discriminatedUnion, An as BaseAddon, D as G711_SCALE_CORRECTION_DB, Dn as DeviceType, Dt as gifDeriveSpeed, En as DeviceFeature, Gn as maskUrlCredentials, Hn as isEvent, I as RATE_CONTROL_RELAXED, In as createEvent, J as addonWidgetsSourceCapability, Kn as nodePin, L as RATE_CONTROL_TIGHT, Mn as CamProfileSchema, Nt as loadContributionCapability, On as errMsg, Ot as gifFromMp4Args, Pt as logChannelsCapability, Qn as boolean, Rt as memoizePinnedFfmpeg, Sn as buildFfmpegArgs, Tn as isSoftwareDecode, Tt as ffmpegRate, Un as makeProfileBrokerId, W as RingBuffer, Wn as makeSourceBrokerId, Xn as _enum, Xt as rankStreams, Zn as array, _t as egressTranscodeSharingKey, ar as record, at as clipExportFailureOf, c as CLIP_STILL_REASON_CODE_HEADER, cr as EventCategory, ct as createHwAccelCache, et as batteryCapability, ft as deriveBatteryPresence, jn as CAM_PROFILE_ORDER, kn as BOOT_RECOVERY_BACKOFF_MS, lt as createLogChannelsProvider, mn as streamBrokerCapability, nr as number, o as BatteryStatusSchema, or as string, qn as parseProfileBrokerId, rn as resolveEgressDecodeHwAccel, rr as object, rt as cameraStreamsCapability, s as CLIP_BROKER_PACED_RATES, sr as union, tr as literal, ut as declareLogChannel, vn as webrtcSessionCapability, vt as egressTransportFromRequest, w as EncodeProfileSchema, wn as invocationFromEncodeProfile, yn as AUDIO_PRESETS, zn as expandAudioChunkToF32le } from "../dist-
|
|
3
|
-
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-
|
|
2
|
+
import { $n as discriminatedUnion, An as BaseAddon, D as G711_SCALE_CORRECTION_DB, Dn as DeviceType, Dt as gifDeriveSpeed, En as DeviceFeature, Gn as maskUrlCredentials, Hn as isEvent, I as RATE_CONTROL_RELAXED, In as createEvent, J as addonWidgetsSourceCapability, Kn as nodePin, L as RATE_CONTROL_TIGHT, Mn as CamProfileSchema, Nt as loadContributionCapability, On as errMsg, Ot as gifFromMp4Args, Pt as logChannelsCapability, Qn as boolean, Rt as memoizePinnedFfmpeg, Sn as buildFfmpegArgs, Tn as isSoftwareDecode, Tt as ffmpegRate, Un as makeProfileBrokerId, W as RingBuffer, Wn as makeSourceBrokerId, Xn as _enum, Xt as rankStreams, Zn as array, _t as egressTranscodeSharingKey, ar as record, at as clipExportFailureOf, c as CLIP_STILL_REASON_CODE_HEADER, cr as EventCategory, ct as createHwAccelCache, et as batteryCapability, ft as deriveBatteryPresence, jn as CAM_PROFILE_ORDER, kn as BOOT_RECOVERY_BACKOFF_MS, lt as createLogChannelsProvider, mn as streamBrokerCapability, nr as number, o as BatteryStatusSchema, or as string, qn as parseProfileBrokerId, rn as resolveEgressDecodeHwAccel, rr as object, rt as cameraStreamsCapability, s as CLIP_BROKER_PACED_RATES, sr as union, tr as literal, ut as declareLogChannel, vn as webrtcSessionCapability, vt as egressTransportFromRequest, w as EncodeProfileSchema, wn as invocationFromEncodeProfile, yn as AUDIO_PRESETS, zn as expandAudioChunkToF32le } from "../dist-CbFPOFAD.mjs";
|
|
3
|
+
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-C-2fB9kH.mjs";
|
|
4
4
|
import { a as parseRestreamPath, d as PREBUFFER_MAX_MS, f as capPreRollRequestMs, i as isLiveEdgeOnlyDial, m as resolvePrebuffer, n as NO_DECLARATION, p as prebufferRetentionMs, s as sdpVariantFor, u as withSentryIntent } from "../restream-intent-DyGmLAU9.mjs";
|
|
5
5
|
import { n as profileForStreamId } from "../remote-restream-BeHi78PZ.mjs";
|
|
6
6
|
import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
|
|
7
|
-
import { a as require_mp4box_all, c as parseNalLengthSize, i as runFfmpegOnce, n as demuxSegmentPreferJs, o as avccSampleToAnnexB, r as FfmpegFallbackRefusedError, s as buildKeyframeAnnexB, t as demuxSegmentFullJs } from "../segment-demux-js-
|
|
7
|
+
import { a as require_mp4box_all, c as parseNalLengthSize, i as runFfmpegOnce, n as demuxSegmentPreferJs, o as avccSampleToAnnexB, r as FfmpegFallbackRefusedError, s as buildKeyframeAnnexB, t as demuxSegmentFullJs } from "../segment-demux-js-D3JBJeN6.mjs";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import * as os$1 from "node:os";
|
|
10
10
|
import { networkInterfaces, tmpdir } from "node:os";
|
|
@@ -2363,6 +2363,10 @@ var PacedRtpReplay = class {
|
|
|
2363
2363
|
this.enqueuedLive++;
|
|
2364
2364
|
return true;
|
|
2365
2365
|
}
|
|
2366
|
+
/** Visit every still-queued item (probe time only; no allocation). */
|
|
2367
|
+
forEachQueued(visit) {
|
|
2368
|
+
for (const item of this.queue) visit(item);
|
|
2369
|
+
}
|
|
2366
2370
|
/** Cancel the replay: pending packets are dropped, `onDone` fires with
|
|
2367
2371
|
* `aborted: true`. Safe to call multiple times / before `start`. */
|
|
2368
2372
|
abort() {
|
|
@@ -3082,6 +3086,133 @@ var RtpPacketizer = class {
|
|
|
3082
3086
|
}
|
|
3083
3087
|
};
|
|
3084
3088
|
//#endregion
|
|
3089
|
+
//#region src/stream-broker/stream-broker/owned-buffer.ts
|
|
3090
|
+
/**
|
|
3091
|
+
* Buffers that enter a LONG-LIVED ring own their backing store.
|
|
3092
|
+
*
|
|
3093
|
+
* Node serves `Buffer.from(...)`, `Buffer.allocUnsafe(n)` and `Buffer.concat`
|
|
3094
|
+
* below `Buffer.poolSize >>> 1` (4 KiB) as views of shared 8 KiB pool slabs.
|
|
3095
|
+
* That is the right choice for the ingest path — a start code, a 4-byte
|
|
3096
|
+
* interleave header, a 1.3 KB RTP packet that is fanned out and forgotten
|
|
3097
|
+
* within a tick — and the wrong one for anything RETAINED: a 600-byte NAL kept
|
|
3098
|
+
* for 60 s in a clip ring pins its whole slab, and with it every short-lived
|
|
3099
|
+
* packet that happened to be allocated beside it. On the hub that held
|
|
3100
|
+
* 550–980 MB of ArrayBuffers for ~150–250 MB of payload, and the full GCs the
|
|
3101
|
+
* pinned slabs caused ran every 0.2–0.5 s at 40–65 % of a core.
|
|
3102
|
+
*
|
|
3103
|
+
* The ring byte caps counted payload bytes, so they never saw it. Both rings
|
|
3104
|
+
* now pass every entry through {@link detachFromPool} on the way in and
|
|
3105
|
+
* account it with {@link backingStoreBytes}, so the cap measures what the
|
|
3106
|
+
* entry costs. Short-lived traffic stays pooled.
|
|
3107
|
+
*/
|
|
3108
|
+
/** True when `buf` is the whole of its ArrayBuffer — nothing else shares it. */
|
|
3109
|
+
function ownsBackingStore(buf) {
|
|
3110
|
+
return buf.byteOffset === 0 && buf.buffer.byteLength === buf.length;
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* What retaining `buf` really costs: its own length when it owns its
|
|
3114
|
+
* ArrayBuffer, the whole shared slab when it is a view of one.
|
|
3115
|
+
*/
|
|
3116
|
+
function backingStoreBytes(buf) {
|
|
3117
|
+
return ownsBackingStore(buf) ? buf.length : buf.buffer.byteLength;
|
|
3118
|
+
}
|
|
3119
|
+
/**
|
|
3120
|
+
* `buf` itself when it already owns its ArrayBuffer (decided by inspecting the
|
|
3121
|
+
* buffer, never by its size: whether a large `allocUnsafe` is pooled is a Node
|
|
3122
|
+
* runtime detail), else a copy that does. One copy, never two: a buffer that is
|
|
3123
|
+
* already unpooled is returned as-is.
|
|
3124
|
+
*/
|
|
3125
|
+
function detachFromPool(buf) {
|
|
3126
|
+
if (ownsBackingStore(buf)) return buf;
|
|
3127
|
+
const owned = Buffer.allocUnsafeSlow(buf.length);
|
|
3128
|
+
buf.copy(owned);
|
|
3129
|
+
return owned;
|
|
3130
|
+
}
|
|
3131
|
+
/**
|
|
3132
|
+
* A copy of `src[start, end)` that OWNS its backing store — the shape a reader
|
|
3133
|
+
* hands out when the packet it cuts from its socket buffer is going to be
|
|
3134
|
+
* retained anyway.
|
|
3135
|
+
*
|
|
3136
|
+
* Every source video packet is: `captureRtpForPreBuffer` keeps it for the life
|
|
3137
|
+
* of a GOP, and the restreamer's keyframe cache keeps the keyframe ones. With
|
|
3138
|
+
* the readers cutting packets as `Buffer.from(subarray)` — a pooled view — the
|
|
3139
|
+
* ring then had to copy each one a second time to own it: two copies of every
|
|
3140
|
+
* packet on the ingest path (measured 15.1 + 14.8 MB/s on the hub's load).
|
|
3141
|
+
* Cutting the packet owned up front makes the ring's and the cache's
|
|
3142
|
+
* `detachFromPool` an identity, so the packet is copied once and shared by the
|
|
3143
|
+
* reader's fan-out, the ring, the cache and every session's write queue.
|
|
3144
|
+
*/
|
|
3145
|
+
function copyOwned(src, start, end) {
|
|
3146
|
+
const owned = Buffer.allocUnsafeSlow(end - start);
|
|
3147
|
+
src.copy(owned, 0, start, end);
|
|
3148
|
+
recordCopyOwned(end - start);
|
|
3149
|
+
return owned;
|
|
3150
|
+
}
|
|
3151
|
+
/** Accumulates entries; each distinct backing ArrayBuffer is summed once. */
|
|
3152
|
+
var BackingTally = class {
|
|
3153
|
+
seen = /* @__PURE__ */ new Set();
|
|
3154
|
+
entries = 0;
|
|
3155
|
+
payload = 0;
|
|
3156
|
+
naive = 0;
|
|
3157
|
+
distinct = 0;
|
|
3158
|
+
capped = false;
|
|
3159
|
+
add(buf) {
|
|
3160
|
+
if (this.entries >= 2e5) {
|
|
3161
|
+
this.capped = true;
|
|
3162
|
+
return;
|
|
3163
|
+
}
|
|
3164
|
+
this.entries += 1;
|
|
3165
|
+
this.payload += buf.length;
|
|
3166
|
+
const backing = backingStoreBytes(buf);
|
|
3167
|
+
this.naive += backing;
|
|
3168
|
+
if (!this.seen.has(buf.buffer)) {
|
|
3169
|
+
this.seen.add(buf.buffer);
|
|
3170
|
+
this.distinct += backing;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
totals() {
|
|
3174
|
+
return {
|
|
3175
|
+
entries: this.entries,
|
|
3176
|
+
payloadBytes: this.payload,
|
|
3177
|
+
naiveBackingBytes: this.naive,
|
|
3178
|
+
distinctBackingBytes: this.distinct,
|
|
3179
|
+
capped: this.capped
|
|
3180
|
+
};
|
|
3181
|
+
}
|
|
3182
|
+
};
|
|
3183
|
+
/** Add every populated slot of a sender's `rtpCache` (≤ RTP_HISTORY_SIZE). */
|
|
3184
|
+
function tallyRtpCache(tally, cache) {
|
|
3185
|
+
if (cache === void 0) return;
|
|
3186
|
+
for (let i = 0; i < cache.length; i++) {
|
|
3187
|
+
const slot = cache[i];
|
|
3188
|
+
if (slot !== void 0) tally.add(slot.payload);
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
/** Distinct backing bytes a session pins across all four structures. */
|
|
3192
|
+
function sessionBackingBytes(r) {
|
|
3193
|
+
return r.rtpCache.distinctBackingBytes + r.pushQueue.distinctBackingBytes + r.rtpReplay.distinctBackingBytes + r.scrub.distinctBackingBytes;
|
|
3194
|
+
}
|
|
3195
|
+
function mbOf(bytes) {
|
|
3196
|
+
return Number((bytes / (1024 * 1024)).toFixed(1));
|
|
3197
|
+
}
|
|
3198
|
+
/** Flat log meta for the session open / close lines. */
|
|
3199
|
+
function sessionMemMeta(r) {
|
|
3200
|
+
return {
|
|
3201
|
+
rtpCacheEntries: r.rtpCache.entries,
|
|
3202
|
+
rtpCachePayloadMb: mbOf(r.rtpCache.payloadBytes),
|
|
3203
|
+
rtpCacheNaiveMb: mbOf(r.rtpCache.naiveBackingBytes),
|
|
3204
|
+
rtpCacheBackingMb: mbOf(r.rtpCache.distinctBackingBytes),
|
|
3205
|
+
pushQueueFrames: r.pushQueue.entries,
|
|
3206
|
+
pushQueueBackingMb: mbOf(r.pushQueue.distinctBackingBytes),
|
|
3207
|
+
rtpReplayPackets: r.rtpReplay.entries,
|
|
3208
|
+
rtpReplayBackingMb: mbOf(r.rtpReplay.distinctBackingBytes),
|
|
3209
|
+
scrubPayloadMb: mbOf(r.scrub.payloadBytes),
|
|
3210
|
+
scrubBackingMb: mbOf(r.scrub.distinctBackingBytes),
|
|
3211
|
+
sessionBackingMb: mbOf(sessionBackingBytes(r)),
|
|
3212
|
+
memCapped: r.rtpCache.capped || r.pushQueue.capped || r.rtpReplay.capped || r.scrub.capped
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
//#endregion
|
|
3085
3216
|
//#region src/stream-broker/stream-broker/broker-mem-probe.ts
|
|
3086
3217
|
/**
|
|
3087
3218
|
* broker-mem-probe — what owns the broker runner's NATIVE memory.
|
|
@@ -3325,8 +3456,58 @@ function formatBrokerMem(input) {
|
|
|
3325
3456
|
const w = input.worker;
|
|
3326
3457
|
if (w !== void 0 && w !== null) parts.push(`workers=${w.workers}`, `workerHeapMb=${mb(w.heapBytes)}`, `workerPhysicalMb=${mb(w.physicalBytes)}`, `workerUsedMb=${mb(w.usedBytes)}`, `workerAgeS=${Math.round(w.maxAgeMs / 1e3)}`, `workerIdleExit=${w.idleTerminates ? "yes" : "never"}`);
|
|
3327
3458
|
parts.push(`brokers=${samples.length}`, `ingesting=${ingesting}`, `annexBPlanes=${planes}`, `rtsp=${rtsp}`, `webrtc=${input.webrtcSessions}`, `encoded=${kindList(consumers)}`, `audioSubs=${audio}`, `pipeClients=${pipe}`, `egress=${input.egressTranscodes}`, `children=${input.childProcesses}`, `opened=${churn.opened}`, `closed=${churn.closed}`, `openedKinds=${kindList(churn.openedByKind)}`, `closedKinds=${kindList(churn.closedByKind)}`, `preBufferMb=${mb(pre)}`, `clipMb=${mb(clip)}`, `rtpRingMb=${mb(rtp)}`, `keyframeMb=${mb(kf)}`, `writeQueueSumMb=${mb(qSum)}`, `writeQueueMaxMb=${mb(qMax)}`, `copiedPackets=${copied.packets}`, `copiedMb=${mb(copied.bytes)}`, `topRingMb=${top === "" ? "none" : top}`);
|
|
3459
|
+
const sessions = input.sessions;
|
|
3460
|
+
if (sessions !== void 0) parts.push(...formatSessionMem(sessions, input));
|
|
3328
3461
|
return parts.join(" ");
|
|
3329
3462
|
}
|
|
3463
|
+
/**
|
|
3464
|
+
* Sums over every WebRTC session, each distinct backing store counted once PER
|
|
3465
|
+
* SESSION, and the three views of the NACK history so pinning shows:
|
|
3466
|
+
* `rtpCachePayloadMb` (what the packets say), `rtpCacheNaiveMb` (each entry's
|
|
3467
|
+
* own backing, a shared slab repeated) and `rtpCacheBackingMb` (each slab once).
|
|
3468
|
+
* `fragMb` is the brk heap NOT explained by v8 external memory.
|
|
3469
|
+
*/
|
|
3470
|
+
function formatSessionMem(sessions, input) {
|
|
3471
|
+
let rtpEntries = 0;
|
|
3472
|
+
let rtpPayload = 0;
|
|
3473
|
+
let rtpNaive = 0;
|
|
3474
|
+
let rtpBacking = 0;
|
|
3475
|
+
let pushFrames = 0;
|
|
3476
|
+
let pushBacking = 0;
|
|
3477
|
+
let replayPackets = 0;
|
|
3478
|
+
let replayBacking = 0;
|
|
3479
|
+
let scrubPayload = 0;
|
|
3480
|
+
let scrubBacking = 0;
|
|
3481
|
+
for (const r of sessions) {
|
|
3482
|
+
rtpEntries += r.rtpCache.entries;
|
|
3483
|
+
rtpPayload += r.rtpCache.payloadBytes;
|
|
3484
|
+
rtpNaive += r.rtpCache.naiveBackingBytes;
|
|
3485
|
+
rtpBacking += r.rtpCache.distinctBackingBytes;
|
|
3486
|
+
pushFrames += r.pushQueue.entries;
|
|
3487
|
+
pushBacking += r.pushQueue.distinctBackingBytes;
|
|
3488
|
+
replayPackets += r.rtpReplay.entries;
|
|
3489
|
+
replayBacking += r.rtpReplay.distinctBackingBytes;
|
|
3490
|
+
scrubPayload += r.scrub.payloadBytes;
|
|
3491
|
+
scrubBacking += r.scrub.distinctBackingBytes;
|
|
3492
|
+
}
|
|
3493
|
+
const top = [...sessions].sort((a, b) => sessionBackingBytes(b) - sessionBackingBytes(a)).slice(0, 3).map((r) => `${r.deviceId ?? "x"}:${mb(sessionBackingBytes(r))}`).join(",");
|
|
3494
|
+
const parts = [
|
|
3495
|
+
`rtpCacheEntries=${rtpEntries}`,
|
|
3496
|
+
`rtpCachePayloadMb=${mb(rtpPayload)}`,
|
|
3497
|
+
`rtpCacheNaiveMb=${mb(rtpNaive)}`,
|
|
3498
|
+
`rtpCacheBackingMb=${mb(rtpBacking)}`,
|
|
3499
|
+
`pushQueueFrames=${pushFrames}`,
|
|
3500
|
+
`pushQueueBackingMb=${mb(pushBacking)}`,
|
|
3501
|
+
`rtpReplayPackets=${replayPackets}`,
|
|
3502
|
+
`rtpReplayBackingMb=${mb(replayBacking)}`,
|
|
3503
|
+
`scrubPayloadMb=${mb(scrubPayload)}`,
|
|
3504
|
+
`scrubBackingMb=${mb(scrubBacking)}`
|
|
3505
|
+
];
|
|
3506
|
+
if (input.arrayBuffersBytes !== void 0) parts.push(`arrayBuffersMb=${mb(input.arrayBuffersBytes)}`);
|
|
3507
|
+
if (input.proc.maps !== null && input.v8 !== void 0 && input.v8 !== null) parts.push(`fragMb=${mb(input.proc.maps.heapBytes - input.v8.externalBytes)}`);
|
|
3508
|
+
parts.push(`topSessionMb=${top === "" ? "none" : top}`);
|
|
3509
|
+
return parts;
|
|
3510
|
+
}
|
|
3330
3511
|
/** Count entries named `name` in `process.getActiveResourcesInfo()`. */
|
|
3331
3512
|
function countActiveResources(resources, name) {
|
|
3332
3513
|
let n = 0;
|
|
@@ -3334,69 +3515,6 @@ function countActiveResources(resources, name) {
|
|
|
3334
3515
|
return n;
|
|
3335
3516
|
}
|
|
3336
3517
|
//#endregion
|
|
3337
|
-
//#region src/stream-broker/stream-broker/owned-buffer.ts
|
|
3338
|
-
/**
|
|
3339
|
-
* Buffers that enter a LONG-LIVED ring own their backing store.
|
|
3340
|
-
*
|
|
3341
|
-
* Node serves `Buffer.from(...)`, `Buffer.allocUnsafe(n)` and `Buffer.concat`
|
|
3342
|
-
* below `Buffer.poolSize >>> 1` (4 KiB) as views of shared 8 KiB pool slabs.
|
|
3343
|
-
* That is the right choice for the ingest path — a start code, a 4-byte
|
|
3344
|
-
* interleave header, a 1.3 KB RTP packet that is fanned out and forgotten
|
|
3345
|
-
* within a tick — and the wrong one for anything RETAINED: a 600-byte NAL kept
|
|
3346
|
-
* for 60 s in a clip ring pins its whole slab, and with it every short-lived
|
|
3347
|
-
* packet that happened to be allocated beside it. On the hub that held
|
|
3348
|
-
* 550–980 MB of ArrayBuffers for ~150–250 MB of payload, and the full GCs the
|
|
3349
|
-
* pinned slabs caused ran every 0.2–0.5 s at 40–65 % of a core.
|
|
3350
|
-
*
|
|
3351
|
-
* The ring byte caps counted payload bytes, so they never saw it. Both rings
|
|
3352
|
-
* now pass every entry through {@link detachFromPool} on the way in and
|
|
3353
|
-
* account it with {@link backingStoreBytes}, so the cap measures what the
|
|
3354
|
-
* entry costs. Short-lived traffic stays pooled.
|
|
3355
|
-
*/
|
|
3356
|
-
/** True when `buf` is the whole of its ArrayBuffer — nothing else shares it. */
|
|
3357
|
-
function ownsBackingStore(buf) {
|
|
3358
|
-
return buf.byteOffset === 0 && buf.buffer.byteLength === buf.length;
|
|
3359
|
-
}
|
|
3360
|
-
/**
|
|
3361
|
-
* What retaining `buf` really costs: its own length when it owns its
|
|
3362
|
-
* ArrayBuffer, the whole shared slab when it is a view of one.
|
|
3363
|
-
*/
|
|
3364
|
-
function backingStoreBytes(buf) {
|
|
3365
|
-
return ownsBackingStore(buf) ? buf.length : buf.buffer.byteLength;
|
|
3366
|
-
}
|
|
3367
|
-
/**
|
|
3368
|
-
* `buf` itself when it already owns its ArrayBuffer (decided by inspecting the
|
|
3369
|
-
* buffer, never by its size: whether a large `allocUnsafe` is pooled is a Node
|
|
3370
|
-
* runtime detail), else a copy that does. One copy, never two: a buffer that is
|
|
3371
|
-
* already unpooled is returned as-is.
|
|
3372
|
-
*/
|
|
3373
|
-
function detachFromPool(buf) {
|
|
3374
|
-
if (ownsBackingStore(buf)) return buf;
|
|
3375
|
-
const owned = Buffer.allocUnsafeSlow(buf.length);
|
|
3376
|
-
buf.copy(owned);
|
|
3377
|
-
return owned;
|
|
3378
|
-
}
|
|
3379
|
-
/**
|
|
3380
|
-
* A copy of `src[start, end)` that OWNS its backing store — the shape a reader
|
|
3381
|
-
* hands out when the packet it cuts from its socket buffer is going to be
|
|
3382
|
-
* retained anyway.
|
|
3383
|
-
*
|
|
3384
|
-
* Every source video packet is: `captureRtpForPreBuffer` keeps it for the life
|
|
3385
|
-
* of a GOP, and the restreamer's keyframe cache keeps the keyframe ones. With
|
|
3386
|
-
* the readers cutting packets as `Buffer.from(subarray)` — a pooled view — the
|
|
3387
|
-
* ring then had to copy each one a second time to own it: two copies of every
|
|
3388
|
-
* packet on the ingest path (measured 15.1 + 14.8 MB/s on the hub's load).
|
|
3389
|
-
* Cutting the packet owned up front makes the ring's and the cache's
|
|
3390
|
-
* `detachFromPool` an identity, so the packet is copied once and shared by the
|
|
3391
|
-
* reader's fan-out, the ring, the cache and every session's write queue.
|
|
3392
|
-
*/
|
|
3393
|
-
function copyOwned(src, start, end) {
|
|
3394
|
-
const owned = Buffer.allocUnsafeSlow(end - start);
|
|
3395
|
-
src.copy(owned, 0, start, end);
|
|
3396
|
-
recordCopyOwned(end - start);
|
|
3397
|
-
return owned;
|
|
3398
|
-
}
|
|
3399
|
-
//#endregion
|
|
3400
3518
|
//#region src/stream-broker/rtsp/sdp-builder.ts
|
|
3401
3519
|
function buildSdp(options) {
|
|
3402
3520
|
const { codec, parameterSets, streamName } = options;
|
|
@@ -24939,6 +25057,23 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
24939
25057
|
} });
|
|
24940
25058
|
}
|
|
24941
25059
|
/** Whether the session has an active feed (vs idle/pooled). */
|
|
25060
|
+
/**
|
|
25061
|
+
* What this session pins outside the heap, by backing store: werift's NACK
|
|
25062
|
+
* history (video + audio, one tally so a slab shared by both counts once) and
|
|
25063
|
+
* the paced replay queue. Probe / lifecycle-line time only — it walks
|
|
25064
|
+
* ≤ 2 × RTP_HISTORY_SIZE slots and the replay tail, never per packet.
|
|
25065
|
+
*/
|
|
25066
|
+
readMemTotals() {
|
|
25067
|
+
const cache = new BackingTally();
|
|
25068
|
+
tallyRtpCache(cache, this.videoSender?.rtpCache);
|
|
25069
|
+
tallyRtpCache(cache, this.audioSender?.rtpCache);
|
|
25070
|
+
const replay = new BackingTally();
|
|
25071
|
+
this.activeRtpReplay?.forEachQueued((pkt) => replay.add(pkt));
|
|
25072
|
+
return {
|
|
25073
|
+
rtpCache: cache.totals(),
|
|
25074
|
+
rtpReplay: replay.totals()
|
|
25075
|
+
};
|
|
25076
|
+
}
|
|
24942
25077
|
get isFeeding() {
|
|
24943
25078
|
return this.feedAbort !== null && !this.feedAbort.signal.aborted;
|
|
24944
25079
|
}
|
|
@@ -28202,6 +28337,13 @@ var ScrubFragmentCache = class {
|
|
|
28202
28337
|
get size() {
|
|
28203
28338
|
return this.map.size;
|
|
28204
28339
|
}
|
|
28340
|
+
/**
|
|
28341
|
+
* Feed every cached access unit to `tally` — the BACKING-store view of what
|
|
28342
|
+
* `byteSize` counts by `.length`. Probe time only (`session-mem.ts`).
|
|
28343
|
+
*/
|
|
28344
|
+
tallyBacking(tally) {
|
|
28345
|
+
for (const frag of this.map.values()) for (const au of frag.aus) tally.add(au.data);
|
|
28346
|
+
}
|
|
28205
28347
|
};
|
|
28206
28348
|
//#endregion
|
|
28207
28349
|
//#region src/stream-broker/recorded/segment-pts-repair.ts
|
|
@@ -35256,7 +35398,8 @@ var BrokerWebrtcServer = class {
|
|
|
35256
35398
|
iceServers: setup.iceServerCount,
|
|
35257
35399
|
codec: setup.sessionCodec,
|
|
35258
35400
|
useRtpRepacketizer: setup.useRtpRepacketizer,
|
|
35259
|
-
relayOnly: opts.relayOnly === true
|
|
35401
|
+
relayOnly: opts.relayOnly === true,
|
|
35402
|
+
...this.sessionMemMetaFor(setup.sessionId)
|
|
35260
35403
|
} });
|
|
35261
35404
|
return {
|
|
35262
35405
|
sessionId: setup.sessionId,
|
|
@@ -35306,7 +35449,8 @@ var BrokerWebrtcServer = class {
|
|
|
35306
35449
|
setupMs,
|
|
35307
35450
|
negotiateMs,
|
|
35308
35451
|
totalMs: Date.now() - offerStart,
|
|
35309
|
-
...setup.setupTimings
|
|
35452
|
+
...setup.setupTimings,
|
|
35453
|
+
...this.sessionMemMetaFor(setup.sessionId)
|
|
35310
35454
|
} });
|
|
35311
35455
|
return {
|
|
35312
35456
|
sessionId: setup.sessionId,
|
|
@@ -35415,7 +35559,7 @@ var BrokerWebrtcServer = class {
|
|
|
35415
35559
|
let framesDroppedSinceLog = 0;
|
|
35416
35560
|
let purgesSinceLog = 0;
|
|
35417
35561
|
let unalignedPurgesSinceLog = 0;
|
|
35418
|
-
const { source, pushFrame, close: closeSource } = createPushFrameSource((count, keyframeAligned) => {
|
|
35562
|
+
const { source, pushFrame, close: closeSource, forEachQueued: forEachQueuedFrame } = createPushFrameSource((count, keyframeAligned) => {
|
|
35419
35563
|
framesDroppedSinceLog += count;
|
|
35420
35564
|
purgesSinceLog += 1;
|
|
35421
35565
|
if (!keyframeAligned) unalignedPurgesSinceLog += 1;
|
|
@@ -35694,6 +35838,7 @@ var BrokerWebrtcServer = class {
|
|
|
35694
35838
|
unsubSdpParams,
|
|
35695
35839
|
unsubSourceRestart,
|
|
35696
35840
|
closeSource,
|
|
35841
|
+
forEachQueuedFrame,
|
|
35697
35842
|
...talkback !== void 0 ? { closeTalkback: () => void talkback.close() } : {},
|
|
35698
35843
|
rebind: {
|
|
35699
35844
|
deviceId,
|
|
@@ -35986,6 +36131,7 @@ var BrokerWebrtcServer = class {
|
|
|
35986
36131
|
})
|
|
35987
36132
|
});
|
|
35988
36133
|
entry.timeline = timeline;
|
|
36134
|
+
entry.scrubCache = scrubCache;
|
|
35989
36135
|
sessionLogger.info("recorded: TimelineSession wired (control accessors present)", { meta: {
|
|
35990
36136
|
sessionId,
|
|
35991
36137
|
deviceId
|
|
@@ -36117,6 +36263,55 @@ var BrokerWebrtcServer = class {
|
|
|
36117
36263
|
return this.sessions.size;
|
|
36118
36264
|
}
|
|
36119
36265
|
/**
|
|
36266
|
+
* One session's pinned-memory reading, by backing store (`session-mem.ts`).
|
|
36267
|
+
* Walks the session's NACK history, push queue, replay tail and scrub cache:
|
|
36268
|
+
* call at probe / lifecycle-line time only.
|
|
36269
|
+
*/
|
|
36270
|
+
readSessionMem(sessionId, entry) {
|
|
36271
|
+
const own = entry.session.readMemTotals();
|
|
36272
|
+
const push = new BackingTally();
|
|
36273
|
+
entry.forEachQueuedFrame((mf) => push.add(mf.frame.data));
|
|
36274
|
+
const scrub = new BackingTally();
|
|
36275
|
+
entry.scrubCache?.tallyBacking(scrub);
|
|
36276
|
+
return {
|
|
36277
|
+
sessionId,
|
|
36278
|
+
deviceId: deviceIdFromBrokerId(entry.brokerId),
|
|
36279
|
+
rtpCache: own.rtpCache,
|
|
36280
|
+
rtpReplay: own.rtpReplay,
|
|
36281
|
+
pushQueue: push.totals(),
|
|
36282
|
+
scrub: scrub.totals()
|
|
36283
|
+
};
|
|
36284
|
+
}
|
|
36285
|
+
/** Every live session's reading, for the `[broker-mem]` line. */
|
|
36286
|
+
getSessionMemReadings() {
|
|
36287
|
+
const readings = [];
|
|
36288
|
+
for (const [sessionId, entry] of this.sessions) try {
|
|
36289
|
+
readings.push(this.readSessionMem(sessionId, entry));
|
|
36290
|
+
} catch (err) {
|
|
36291
|
+
this.logger.warn("session memory reading failed", {
|
|
36292
|
+
tags: { deviceId: deviceIdFromBrokerId(entry.brokerId) },
|
|
36293
|
+
meta: {
|
|
36294
|
+
sessionId,
|
|
36295
|
+
error: errMsg(err)
|
|
36296
|
+
}
|
|
36297
|
+
});
|
|
36298
|
+
}
|
|
36299
|
+
return readings;
|
|
36300
|
+
}
|
|
36301
|
+
/** The counters a lifecycle line carries; empty when the session is gone. */
|
|
36302
|
+
sessionMemMetaFor(sessionId) {
|
|
36303
|
+
const entry = this.sessions.get(sessionId);
|
|
36304
|
+
if (entry === void 0) return {};
|
|
36305
|
+
try {
|
|
36306
|
+
return sessionMemMeta(this.readSessionMem(sessionId, entry));
|
|
36307
|
+
} catch (err) {
|
|
36308
|
+
return {
|
|
36309
|
+
memReadFailed: true,
|
|
36310
|
+
memReadError: errMsg(err)
|
|
36311
|
+
};
|
|
36312
|
+
}
|
|
36313
|
+
}
|
|
36314
|
+
/**
|
|
36120
36315
|
* People watching LIVE through this server, per camera (`live-viewers.ts`):
|
|
36121
36316
|
* sessions of a viewer kind whose track is on the live edge. A session on a
|
|
36122
36317
|
* recorded playhead is not watching live; the system's own subscriptions
|
|
@@ -36925,6 +37120,15 @@ var BrokerWebrtcServer = class {
|
|
|
36925
37120
|
cleanupSession(sessionId) {
|
|
36926
37121
|
const entry = this.sessions.get(sessionId);
|
|
36927
37122
|
if (!entry) return;
|
|
37123
|
+
const deviceId = deviceIdFromBrokerId(entry.brokerId);
|
|
37124
|
+
this.logger.info("WebRTC session closing: pinned-memory counters", {
|
|
37125
|
+
tags: { deviceId },
|
|
37126
|
+
meta: {
|
|
37127
|
+
sessionId,
|
|
37128
|
+
deviceId,
|
|
37129
|
+
...this.sessionMemMetaFor(sessionId)
|
|
37130
|
+
}
|
|
37131
|
+
});
|
|
36928
37132
|
this.sessions.delete(sessionId);
|
|
36929
37133
|
reportConsumerEvent(this.logger, "detach", `webrtc:${entry.consumerKind}`, entry.rebind?.deviceId, this.sessions.size);
|
|
36930
37134
|
entry.pendingSwitch?.cancel();
|
|
@@ -37119,28 +37323,33 @@ function createPushFrameSource(onFramesDropped) {
|
|
|
37119
37323
|
});
|
|
37120
37324
|
}
|
|
37121
37325
|
};
|
|
37122
|
-
|
|
37123
|
-
|
|
37124
|
-
|
|
37125
|
-
|
|
37126
|
-
|
|
37127
|
-
|
|
37128
|
-
|
|
37129
|
-
continue;
|
|
37130
|
-
}
|
|
37131
|
-
if (done) return;
|
|
37132
|
-
const result = await new Promise((r) => {
|
|
37133
|
-
resolve = r;
|
|
37134
|
-
});
|
|
37135
|
-
if (result.done) return;
|
|
37136
|
-
yield result.value;
|
|
37326
|
+
const source = (async function* () {
|
|
37327
|
+
try {
|
|
37328
|
+
while (true) {
|
|
37329
|
+
const item = queue.shift();
|
|
37330
|
+
if (item) {
|
|
37331
|
+
yield item;
|
|
37332
|
+
continue;
|
|
37137
37333
|
}
|
|
37138
|
-
|
|
37139
|
-
|
|
37334
|
+
if (done) return;
|
|
37335
|
+
const result = await new Promise((r) => {
|
|
37336
|
+
resolve = r;
|
|
37337
|
+
});
|
|
37338
|
+
if (result.done) return;
|
|
37339
|
+
yield result.value;
|
|
37140
37340
|
}
|
|
37141
|
-
}
|
|
37341
|
+
} finally {
|
|
37342
|
+
done = true;
|
|
37343
|
+
}
|
|
37344
|
+
})();
|
|
37345
|
+
const forEachQueued = (visit) => {
|
|
37346
|
+
for (const frame of queue) visit(frame);
|
|
37347
|
+
};
|
|
37348
|
+
return {
|
|
37349
|
+
source,
|
|
37142
37350
|
pushFrame,
|
|
37143
|
-
close
|
|
37351
|
+
close,
|
|
37352
|
+
forEachQueued
|
|
37144
37353
|
};
|
|
37145
37354
|
}
|
|
37146
37355
|
//#endregion
|
|
@@ -37674,7 +37883,9 @@ async function emitOnce(deps) {
|
|
|
37674
37883
|
churn: consumerChurn.drain(),
|
|
37675
37884
|
copied: readCopyOwnedTotals(),
|
|
37676
37885
|
v8: readV8Heap(),
|
|
37677
|
-
worker
|
|
37886
|
+
worker,
|
|
37887
|
+
sessions: deps.sessionMem(),
|
|
37888
|
+
arrayBuffersBytes: process.memoryUsage().arrayBuffers
|
|
37678
37889
|
});
|
|
37679
37890
|
deps.logger.info(line);
|
|
37680
37891
|
}
|
|
@@ -38225,7 +38436,8 @@ var StreamBrokerAddon = class extends BaseAddon {
|
|
|
38225
38436
|
this.stopBrokerMemReport = startBrokerMemReport({
|
|
38226
38437
|
logger: this.ctx.logger,
|
|
38227
38438
|
manager: this.brokerManager,
|
|
38228
|
-
webrtcSessions: () => webrtcServer.getSessionCount()
|
|
38439
|
+
webrtcSessions: () => webrtcServer.getSessionCount(),
|
|
38440
|
+
sessionMem: () => webrtcServer.getSessionMemReadings()
|
|
38229
38441
|
});
|
|
38230
38442
|
const widgetsProvider = { listWidgets: async () => [{
|
|
38231
38443
|
tab: "device-tab",
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DwwDKaZJ.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.370",
|
|
4
4
|
"description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|