@myzonerocks/gosslens 0.11.0 → 0.11.1
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/src/index.d.ts.map +1 -1
- package/dist/src/index.js +50 -43
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +45 -42
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -527,8 +527,12 @@ export class GossEngine {
|
|
|
527
527
|
// itself, via emscripten_webgl_create_context - passing
|
|
528
528
|
// webGLContextAttributes here has no effect regardless,
|
|
529
529
|
// preserveDrawingBuffer stays false. Worked around in capturePixels.
|
|
530
|
-
|
|
531
|
-
|
|
530
|
+
let rendererStatus: number;
|
|
531
|
+
try {
|
|
532
|
+
rendererStatus = await mod.ccall("goss_engine_init_renderer", "number", ["number", "number"], [this.handle, rendererDescPtr], { async: true });
|
|
533
|
+
} finally {
|
|
534
|
+
mod.ccall("goss_free", null, ["number", "number"], [rendererDescPtr, 12]);
|
|
535
|
+
}
|
|
532
536
|
if (rendererStatus !== GOSS_OK) throw new Error(`renderer init failed: ${rendererStatus}`);
|
|
533
537
|
|
|
534
538
|
// Emscripten's C++ side just created this canvas's own rendering
|
|
@@ -1132,7 +1136,8 @@ export class GossSession {
|
|
|
1132
1136
|
if (bytes > this.scratchCapacity) {
|
|
1133
1137
|
if (this.scratchPtr !== 0) this.mod.ccall("goss_free", null, ["number", "number"], [this.scratchPtr, this.scratchCapacity]);
|
|
1134
1138
|
this.scratchPtr = this.mod.ccall("goss_alloc", "number", ["number"], [bytes]) as number;
|
|
1135
|
-
this.scratchCapacity = bytes;
|
|
1139
|
+
this.scratchCapacity = this.scratchPtr === 0 ? 0 : bytes;
|
|
1140
|
+
if (this.scratchPtr === 0) throw new Error("wasm allocation failed");
|
|
1136
1141
|
}
|
|
1137
1142
|
return this.scratchPtr;
|
|
1138
1143
|
}
|
|
@@ -1293,7 +1298,7 @@ export class GossSession {
|
|
|
1293
1298
|
/// muxed recording track, unused by the web preview path.
|
|
1294
1299
|
submitAudio(samples: Float32Array, frameCount: number, sampleRate: number, channels: number, timestampUs: bigint = 0n): void {
|
|
1295
1300
|
const bytes = samples.length * 4;
|
|
1296
|
-
const ptr = this.
|
|
1301
|
+
const ptr = this.scratch(bytes);
|
|
1297
1302
|
this.mod.HEAPF32.set(samples, ptr >> 2);
|
|
1298
1303
|
this.mod.ccall(
|
|
1299
1304
|
"goss_session_submit_audio",
|
|
@@ -1301,18 +1306,15 @@ export class GossSession {
|
|
|
1301
1306
|
["number", "number", "number", "number", "number", "number"],
|
|
1302
1307
|
[this.handle, ptr, frameCount, sampleRate, channels, timestampUs],
|
|
1303
1308
|
);
|
|
1304
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [ptr, bytes]);
|
|
1305
1309
|
}
|
|
1306
1310
|
|
|
1307
1311
|
/// Pulls the next block of mixed lens audio (frames interleaved s16) that
|
|
1308
1312
|
/// play_sound triggers produced, for the page to feed into WebAudio.
|
|
1309
1313
|
pullAudio(frames: number): Int16Array {
|
|
1310
1314
|
const byteLen = frames * 2;
|
|
1311
|
-
const ptr = this.
|
|
1315
|
+
const ptr = this.scratch(byteLen);
|
|
1312
1316
|
this.mod.ccall("goss_session_pull_audio", "number", ["number", "number", "number"], [this.handle, ptr, frames]);
|
|
1313
|
-
|
|
1314
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [ptr, byteLen]);
|
|
1315
|
-
return out;
|
|
1317
|
+
return new Int16Array(this.mod.HEAP16.buffer, ptr, frames).slice();
|
|
1316
1318
|
}
|
|
1317
1319
|
|
|
1318
1320
|
/// Folds the active lens sound into the caller's outgoing call/live track:
|
|
@@ -1321,12 +1323,12 @@ export class GossSession {
|
|
|
1321
1323
|
/// mixed interleaved s16. Advances the mixer once, replacing `pullAudio`.
|
|
1322
1324
|
mixOutputAudio(mic: Float32Array | null, frameCount: number, sampleRate: number, channels: number): Int16Array {
|
|
1323
1325
|
const outLen = frameCount * channels;
|
|
1324
|
-
const outBytes = outLen * 2;
|
|
1325
|
-
const outPtr = this.mod.ccall("goss_alloc", "number", ["number"], [outBytes]);
|
|
1326
|
-
let micPtr = 0;
|
|
1326
|
+
const outBytes = (outLen * 2 + 3) & ~3;
|
|
1327
1327
|
const micBytes = mic ? mic.length * 4 : 0;
|
|
1328
|
+
const outPtr = this.scratch(outBytes + micBytes);
|
|
1329
|
+
let micPtr = 0;
|
|
1328
1330
|
if (mic) {
|
|
1329
|
-
micPtr =
|
|
1331
|
+
micPtr = outPtr + outBytes;
|
|
1330
1332
|
this.mod.HEAPF32.set(mic, micPtr >> 2);
|
|
1331
1333
|
}
|
|
1332
1334
|
this.mod.ccall(
|
|
@@ -1335,10 +1337,7 @@ export class GossSession {
|
|
|
1335
1337
|
["number", "number", "number", "number", "number", "number"],
|
|
1336
1338
|
[this.handle, micPtr, outPtr, frameCount, sampleRate, channels],
|
|
1337
1339
|
);
|
|
1338
|
-
|
|
1339
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [outPtr, outBytes]);
|
|
1340
|
-
if (mic) this.mod.ccall("goss_free", null, ["number", "number"], [micPtr, micBytes]);
|
|
1341
|
-
return out;
|
|
1340
|
+
return new Int16Array(this.mod.HEAP16.buffer, outPtr, outLen).slice();
|
|
1342
1341
|
}
|
|
1343
1342
|
|
|
1344
1343
|
/// Stores validated camera-hardware intent; the engine normalizes it. Read it
|
|
@@ -1483,7 +1482,7 @@ export class GossSession {
|
|
|
1483
1482
|
/// Uploads one RGBA/BGRA frame into a named source (pixelFormat 3 BGRA, 4 RGBA).
|
|
1484
1483
|
submitSourceFrameRgba(name: string, rgba: Uint8Array, width: number, height: number, stride: number, pixelFormat: GossPixelFormat = GossPixelFormat.Rgba8): void {
|
|
1485
1484
|
const byteLen = stride * height;
|
|
1486
|
-
const rgbaPtr = this.
|
|
1485
|
+
const rgbaPtr = this.scratch(byteLen);
|
|
1487
1486
|
this.mod.HEAPU8.set(rgba.subarray(0, byteLen), rgbaPtr);
|
|
1488
1487
|
this.mod.setValue(this.frameDescPtr, width, "i32");
|
|
1489
1488
|
this.mod.setValue(this.frameDescPtr + 4, height, "i32");
|
|
@@ -1495,7 +1494,6 @@ export class GossSession {
|
|
|
1495
1494
|
this.mod.setValue(this.frameDescPtr + 28, 0, "i32");
|
|
1496
1495
|
this.withName(name, (ptr, len) =>
|
|
1497
1496
|
this.mod.ccall("goss_session_submit_source_frame_rgba_copy", "number", ["number", "number", "number", "number", "number", "number"], [this.handle, ptr, len, this.frameDescPtr, rgbaPtr, stride]));
|
|
1498
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [rgbaPtr, byteLen]);
|
|
1499
1497
|
}
|
|
1500
1498
|
|
|
1501
1499
|
/// Arranges the camera and named sources: 0 custom, 1 side-by-side, 2 top-bottom, 3 pip, 4 grid.
|
|
@@ -1798,7 +1796,7 @@ export class GossSession {
|
|
|
1798
1796
|
}
|
|
1799
1797
|
const scaleX = this.frameWidth / sourceWidth;
|
|
1800
1798
|
const scaleY = this.frameHeight / sourceHeight;
|
|
1801
|
-
const pointCount = landmarks.length / 3;
|
|
1799
|
+
const pointCount = Math.min(landmarks.length / 3, GOSS_FACE_LANDMARK_COUNT);
|
|
1802
1800
|
const base = this.landmarksPtr >> 2;
|
|
1803
1801
|
for (let at = 0; at < pointCount; at += 1) {
|
|
1804
1802
|
this.mod.HEAPF32[base + at * 3] = landmarks[at * 3]! * scaleX;
|
|
@@ -1829,15 +1827,15 @@ export class GossSession {
|
|
|
1829
1827
|
const off = i * FACE_RESULT_BYTES;
|
|
1830
1828
|
const base = ptr + off;
|
|
1831
1829
|
const f = faces[i]!;
|
|
1832
|
-
const count = f.landmarks.length / 3;
|
|
1830
|
+
const count = Math.min(f.landmarks.length / 3, GOSS_FACE_LANDMARK_COUNT);
|
|
1833
1831
|
dv.setBigUint64(off, BigInt(f.frameSerial ?? 0), true);
|
|
1834
1832
|
dv.setBigInt64(off + 8, BigInt(f.timestampUs ?? 0), true);
|
|
1835
1833
|
dv.setFloat32(off + 16, f.presence ?? 1, true);
|
|
1836
1834
|
dv.setUint32(off + 20, count, true);
|
|
1837
|
-
this.mod.HEAPF32.set(f.landmarks, (base + 24) >> 2);
|
|
1835
|
+
this.mod.HEAPF32.set(f.landmarks.subarray(0, count * 3), (base + 24) >> 2);
|
|
1838
1836
|
const bsStart = (base + 24 + GOSS_FACE_LANDMARK_COUNT * 3 * 4) >> 2;
|
|
1839
1837
|
this.mod.HEAPF32.fill(0, bsStart, bsStart + GOSS_FACE_BLENDSHAPE_COUNT);
|
|
1840
|
-
if (f.blendshapes) this.mod.HEAPF32.set(f.blendshapes, bsStart);
|
|
1838
|
+
if (f.blendshapes) this.mod.HEAPF32.set(f.blendshapes.subarray(0, GOSS_FACE_BLENDSHAPE_COUNT), bsStart);
|
|
1841
1839
|
}
|
|
1842
1840
|
this.mod.ccall("goss_session_submit_faces", "number", ["number", "number", "number"], [this.handle, ptr, faces.length]);
|
|
1843
1841
|
}
|
|
@@ -1894,16 +1892,16 @@ export class GossSession {
|
|
|
1894
1892
|
const off = i * POSE_RESULT_BYTES;
|
|
1895
1893
|
const base = ptr + off;
|
|
1896
1894
|
const b = bodies[i]!;
|
|
1897
|
-
const count = b.landmarks.length / 3;
|
|
1895
|
+
const count = Math.min(b.landmarks.length / 3, GOSS_POSE_LANDMARK_COUNT);
|
|
1898
1896
|
dv.setBigUint64(off, BigInt(b.frameSerial ?? 0), true);
|
|
1899
1897
|
dv.setBigInt64(off + 8, BigInt(b.timestampUs ?? 0), true);
|
|
1900
1898
|
dv.setFloat32(off + 16, b.presence ?? 1, true);
|
|
1901
1899
|
dv.setUint32(off + 20, count, true);
|
|
1902
|
-
this.mod.HEAPF32.set(b.landmarks, (base + 24) >> 2);
|
|
1900
|
+
this.mod.HEAPF32.set(b.landmarks.subarray(0, count * 3), (base + 24) >> 2);
|
|
1903
1901
|
const visStart = (base + 24 + GOSS_POSE_LANDMARK_COUNT * 3 * 4) >> 2;
|
|
1904
1902
|
this.mod.HEAPF32.fill(0, visStart, visStart + GOSS_POSE_LANDMARK_COUNT * 2);
|
|
1905
|
-
if (b.visibilities) this.mod.HEAPF32.set(b.visibilities, visStart);
|
|
1906
|
-
if (b.presences) this.mod.HEAPF32.set(b.presences, visStart + GOSS_POSE_LANDMARK_COUNT);
|
|
1903
|
+
if (b.visibilities) this.mod.HEAPF32.set(b.visibilities.subarray(0, GOSS_POSE_LANDMARK_COUNT), visStart);
|
|
1904
|
+
if (b.presences) this.mod.HEAPF32.set(b.presences.subarray(0, GOSS_POSE_LANDMARK_COUNT), visStart + GOSS_POSE_LANDMARK_COUNT);
|
|
1907
1905
|
}
|
|
1908
1906
|
this.mod.ccall("goss_session_submit_bodies", "number", ["number", "number", "number"], [this.handle, ptr, bodies.length]);
|
|
1909
1907
|
}
|
|
@@ -2215,9 +2213,9 @@ export class GossSession {
|
|
|
2215
2213
|
/// Submits one NV12 exposure of an HDR bracket, fed to bracket-source
|
|
2216
2214
|
/// temporal.fuse nodes. y and uv are the plane bytes as submitFrameCopy takes.
|
|
2217
2215
|
submitFrameBracket(y: Uint8Array, yStride: number, uv: Uint8Array, uvStride: number, width: number, height: number, colorStandard = 1, colorRange = 0): void {
|
|
2218
|
-
const yPtr = this.
|
|
2216
|
+
const yPtr = this.scratch(y.length + uv.length);
|
|
2219
2217
|
this.mod.HEAPU8.set(y, yPtr);
|
|
2220
|
-
const uvPtr =
|
|
2218
|
+
const uvPtr = yPtr + y.length;
|
|
2221
2219
|
this.mod.HEAPU8.set(uv, uvPtr);
|
|
2222
2220
|
this.mod.setValue(this.frameDescPtr, width, "i32");
|
|
2223
2221
|
this.mod.setValue(this.frameDescPtr + 4, height, "i32");
|
|
@@ -2228,14 +2226,12 @@ export class GossSession {
|
|
|
2228
2226
|
this.mod.setValue(this.frameDescPtr + 24, 0, "i32");
|
|
2229
2227
|
this.mod.setValue(this.frameDescPtr + 28, 0, "i32");
|
|
2230
2228
|
this.mod.ccall("goss_session_submit_frame_bracket", "number", ["number", "number", "number", "number", "number", "number"], [this.handle, this.frameDescPtr, yPtr, yStride, uvPtr, uvStride]);
|
|
2231
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [yPtr, y.length]);
|
|
2232
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [uvPtr, uv.length]);
|
|
2233
2229
|
}
|
|
2234
2230
|
|
|
2235
2231
|
private submitPlanes(sym: string, y: Uint8Array, yStride: number, uv: Uint8Array, uvStride: number, width: number, height: number, colorStandard: number, colorRange: number): void {
|
|
2236
|
-
const yPtr = this.
|
|
2232
|
+
const yPtr = this.scratch(y.length + uv.length);
|
|
2237
2233
|
this.mod.HEAPU8.set(y, yPtr);
|
|
2238
|
-
const uvPtr =
|
|
2234
|
+
const uvPtr = yPtr + y.length;
|
|
2239
2235
|
this.mod.HEAPU8.set(uv, uvPtr);
|
|
2240
2236
|
this.mod.setValue(this.frameDescPtr, width, "i32");
|
|
2241
2237
|
this.mod.setValue(this.frameDescPtr + 4, height, "i32");
|
|
@@ -2246,8 +2242,6 @@ export class GossSession {
|
|
|
2246
2242
|
this.mod.setValue(this.frameDescPtr + 24, 0, "i32");
|
|
2247
2243
|
this.mod.setValue(this.frameDescPtr + 28, 0, "i32");
|
|
2248
2244
|
this.mod.ccall(sym, "number", ["number", "number", "number", "number", "number", "number"], [this.handle, this.frameDescPtr, yPtr, yStride, uvPtr, uvStride]);
|
|
2249
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [yPtr, y.length]);
|
|
2250
|
-
this.mod.ccall("goss_free", null, ["number", "number"], [uvPtr, uv.length]);
|
|
2251
2245
|
}
|
|
2252
2246
|
|
|
2253
2247
|
/// Feeds one NV12 frame to the in-engine trackers only (no render), for a host
|
|
@@ -2626,7 +2620,8 @@ export class GossSession {
|
|
|
2626
2620
|
if (this.framePixelsCapacity >= byteLength) return;
|
|
2627
2621
|
if (this.framePixelsPtr !== 0) this.mod.ccall("goss_free", null, ["number", "number"], [this.framePixelsPtr, this.framePixelsCapacity]);
|
|
2628
2622
|
this.framePixelsPtr = this.mod.ccall("goss_alloc", "number", ["number"], [byteLength]);
|
|
2629
|
-
this.framePixelsCapacity = byteLength;
|
|
2623
|
+
this.framePixelsCapacity = this.framePixelsPtr === 0 ? 0 : byteLength;
|
|
2624
|
+
if (this.framePixelsPtr === 0) throw new Error("wasm allocation failed");
|
|
2630
2625
|
}
|
|
2631
2626
|
|
|
2632
2627
|
/// rotationDegrees omitted means the setVideoFlip state decides (a
|
|
@@ -2729,7 +2724,8 @@ export class GossSession {
|
|
|
2729
2724
|
if (this.worldScratchLen >= byteLength) return;
|
|
2730
2725
|
if (this.worldScratchPtr !== 0) this.mod.ccall("goss_free", null, ["number", "number"], [this.worldScratchPtr, this.worldScratchLen]);
|
|
2731
2726
|
this.worldScratchPtr = this.mod.ccall("goss_alloc", "number", ["number"], [byteLength]);
|
|
2732
|
-
this.worldScratchLen = byteLength;
|
|
2727
|
+
this.worldScratchLen = this.worldScratchPtr === 0 ? 0 : byteLength;
|
|
2728
|
+
if (this.worldScratchPtr === 0) throw new Error("wasm allocation failed");
|
|
2733
2729
|
}
|
|
2734
2730
|
|
|
2735
2731
|
/// Reports one finished frame: measured whole-pipeline time plus
|
|
@@ -2805,9 +2801,14 @@ export class GossPreviewSession {
|
|
|
2805
2801
|
static async create(canvas: HTMLCanvasElement, wasmJsUrl: string | URL, events: GossSessionEvents = {}): Promise<GossPreviewSession> {
|
|
2806
2802
|
const gosslens = await Gosslens.load(canvas, wasmJsUrl);
|
|
2807
2803
|
const engine = GossEngine.create(gosslens);
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2804
|
+
try {
|
|
2805
|
+
await engine.initRenderer(canvas);
|
|
2806
|
+
const session = GossSession.create(engine);
|
|
2807
|
+
return new GossPreviewSession(gosslens, engine, session, events);
|
|
2808
|
+
} catch (err) {
|
|
2809
|
+
engine.destroy();
|
|
2810
|
+
throw err;
|
|
2811
|
+
}
|
|
2811
2812
|
}
|
|
2812
2813
|
|
|
2813
2814
|
abiVersion(): number {
|
|
@@ -2936,8 +2937,10 @@ export class GossPreviewSession {
|
|
|
2936
2937
|
this.cameraFrames += 1;
|
|
2937
2938
|
const width = this.video.videoWidth;
|
|
2938
2939
|
const height = this.video.videoHeight;
|
|
2939
|
-
this.scratchCanvas.width
|
|
2940
|
-
|
|
2940
|
+
if (this.scratchCanvas.width !== width || this.scratchCanvas.height !== height) {
|
|
2941
|
+
this.scratchCanvas.width = width;
|
|
2942
|
+
this.scratchCanvas.height = height;
|
|
2943
|
+
}
|
|
2941
2944
|
this.scratchCtx.drawImage(this.video, 0, 0, width, height);
|
|
2942
2945
|
const pixels = this.scratchCtx.getImageData(0, 0, width, height);
|
|
2943
2946
|
// Not mirrored here - the demo page's own CSS mirrors the canvas
|