@zappar/zappar-cv 0.4.0-beta.4 → 0.4.0-beta.7
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/CHANGELOG.md +79 -34
- package/README.md +2 -2
- package/lib/camera-source-map.d.ts +10 -0
- package/lib/camera-source-map.js +40 -0
- package/lib/camera-source.d.ts +2 -5
- package/lib/camera-source.js +3 -13
- package/lib/compatibility.js +1 -1
- package/lib/drawcamera.js +2 -1
- package/lib/gen/zappar-client.js +6 -1
- package/lib/gen/zappar-cwrap.js +37 -21
- package/lib/gen/zappar-native.d.ts +11 -0
- package/lib/gen/zappar-native.js +13 -1
- package/lib/gen/zappar-server.js +1 -1
- package/lib/gen/zappar.d.ts +5 -0
- package/lib/gen/zappar.js +5 -3
- package/lib/gfx.d.ts +1 -0
- package/lib/gfx.js +4 -0
- package/lib/html-element-source.d.ts +3 -20
- package/lib/html-element-source.js +19 -263
- package/lib/image-process-gl.d.ts +37 -0
- package/lib/image-process-gl.js +265 -0
- package/lib/imagebitmap-camera-source.d.ts +36 -0
- package/lib/imagebitmap-camera-source.js +277 -0
- package/lib/mstp-camera-source.d.ts +29 -0
- package/lib/mstp-camera-source.js +230 -0
- package/lib/native.js +45 -8
- package/lib/pipeline.d.ts +13 -3
- package/lib/pipeline.js +95 -26
- package/lib/profile.d.ts +2 -0
- package/lib/profile.js +55 -44
- package/lib/sequencerecorder.d.ts +1 -0
- package/lib/sequencerecorder.js +11 -0
- package/lib/sequencesource.d.ts +7 -1
- package/lib/sequencesource.js +89 -47
- package/lib/source.d.ts +6 -4
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/worker-client.js +0 -5
- package/lib/worker-imagebitmap.d.ts +5 -0
- package/lib/worker-imagebitmap.js +63 -0
- package/lib/worker-server.d.ts +0 -5
- package/lib/worker-server.js +120 -24
- package/lib/workerinterface.d.ts +47 -1
- package/lib/zcv.js +26 -26
- package/lib/zcv.wasm +0 -0
- package/package.json +34 -31
- package/umd/{d115e485cffe500afc4f7c1272ea8f62.wasm → 9d9c4b542b40c41e3ef7587fb91e5d38.wasm} +0 -0
- package/umd/zappar-cv.js +1 -9
- package/umd/zappar-cv.worker.js +1 -1
- package/lib/bundleworker-mainthread.d.ts +0 -2
- package/lib/bundleworker-mainthread.js +0 -36
- package/lib/bundleworker-worker.d.ts +0 -6
- package/lib/bundleworker-worker.js +0 -34
- package/lib/zcv-slam.js +0 -16
- package/lib/zcv-slam.wasm +0 -0
- package/umd/1ec038c18c27f4adf35917a8175401f0.wasm +0 -0
- package/umd/9c0b0dcf514b48c05541.bundleworker.js +0 -1
package/lib/profile.js
CHANGED
|
@@ -17,56 +17,67 @@ exports.profile = {
|
|
|
17
17
|
videoHeight: 480,
|
|
18
18
|
dataWidth: 320,
|
|
19
19
|
dataHeight: 240,
|
|
20
|
-
videoElementInDOM: false
|
|
20
|
+
videoElementInDOM: false,
|
|
21
|
+
preferMediaStreamTrackProcessorCamera: false,
|
|
22
|
+
preferImageBitmapCamera: false
|
|
21
23
|
};
|
|
22
|
-
window
|
|
24
|
+
if (typeof window !== "undefined") {
|
|
25
|
+
window["zeeProfile"] = exports.profile;
|
|
26
|
+
if (window.location.href.indexOf("_mstppipeline") >= 0) {
|
|
27
|
+
console.log("Configuring for MSTP camera pipeline (if supported)");
|
|
28
|
+
exports.profile.preferMediaStreamTrackProcessorCamera = true;
|
|
29
|
+
}
|
|
30
|
+
if (window.location.href.indexOf("_imagebitmappipeline") >= 0) {
|
|
31
|
+
console.log("Configuring for ImageBitmap camera pipeline (if supported)");
|
|
32
|
+
exports.profile.preferImageBitmapCamera = true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
23
35
|
let agent = new UAParser.UAParser();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
navigator.mediaDevices.getSupportedConstraints().frameRate) {
|
|
64
|
-
exports.profile.requestHighFrameRate = true;
|
|
36
|
+
let os = (agent.getOS().name || "unknown").toLowerCase();
|
|
37
|
+
let engine = (agent.getEngine().name || "unknown").toLowerCase();
|
|
38
|
+
if (engine === "webkit" && os !== "ios") {
|
|
39
|
+
exports.profile.deviceMotionMutliplier = 1.0;
|
|
40
|
+
if (typeof window !== "undefined" && window.orientation !== undefined) {
|
|
41
|
+
// iPad
|
|
42
|
+
iDevice();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (engine === "webkit" && os === "ios") {
|
|
46
|
+
exports.profile.deviceMotionMutliplier = 1.0;
|
|
47
|
+
iDevice();
|
|
48
|
+
}
|
|
49
|
+
function iDevice() {
|
|
50
|
+
let version = agent.getOS().version;
|
|
51
|
+
if (version) {
|
|
52
|
+
let versionParts = version.split(".");
|
|
53
|
+
if (versionParts.length >= 2) {
|
|
54
|
+
const majorVersion = parseInt(versionParts[0]);
|
|
55
|
+
const minorVersion = parseInt(versionParts[1]);
|
|
56
|
+
if (majorVersion < 11 ||
|
|
57
|
+
(majorVersion === 11 && minorVersion < 3)) {
|
|
58
|
+
exports.profile.blacklisted = true;
|
|
59
|
+
}
|
|
60
|
+
if (majorVersion < 12 ||
|
|
61
|
+
(majorVersion === 12 && minorVersion < 2)) {
|
|
62
|
+
exports.profile.videoElementInDOM = true;
|
|
63
|
+
}
|
|
64
|
+
if ((majorVersion === 12 && minorVersion >= 2) || (majorVersion >= 13))
|
|
65
|
+
exports.profile.showGyroPermissionsWarningIfNecessary = true;
|
|
66
|
+
if (majorVersion >= 13) {
|
|
67
|
+
exports.profile.showSafariPermissionsResetIfNecessary = true;
|
|
68
|
+
}
|
|
69
|
+
if (((majorVersion >= 12 && minorVersion > 1) || (majorVersion >= 13)) &&
|
|
70
|
+
navigator.mediaDevices &&
|
|
71
|
+
navigator.mediaDevices.getSupportedConstraints &&
|
|
72
|
+
navigator.mediaDevices.getSupportedConstraints().frameRate) {
|
|
73
|
+
exports.profile.requestHighFrameRate = true;
|
|
74
|
+
if (majorVersion < 14) {
|
|
65
75
|
// Avoid bug where iOS letterboxes 16:9 into 4:3 for high fps
|
|
76
|
+
// Doesn't seem needed with newer versions of iOS, tested on 14.8.1 and 15.2
|
|
66
77
|
exports.profile.videoHeight = 360;
|
|
67
78
|
exports.profile.dataHeight = 180;
|
|
68
79
|
}
|
|
69
80
|
}
|
|
70
81
|
}
|
|
71
|
-
|
|
82
|
+
}
|
|
72
83
|
}
|
package/lib/sequencerecorder.js
CHANGED
|
@@ -15,6 +15,7 @@ class SequenceRecorder {
|
|
|
15
15
|
this._insertionByte = 0;
|
|
16
16
|
this._numberPackets = 0;
|
|
17
17
|
this._started = false;
|
|
18
|
+
this._hasLoggedUnsuppored = false;
|
|
18
19
|
this._data = new ArrayBuffer(this._estimatedSize(estimatedFrames, 320, 240));
|
|
19
20
|
this._dataView = new DataView(this._data);
|
|
20
21
|
this._dataUint8 = new Uint8Array(this._data);
|
|
@@ -38,6 +39,9 @@ class SequenceRecorder {
|
|
|
38
39
|
this._started = false;
|
|
39
40
|
let trimmed = this._data.slice(0, this._insertionByte);
|
|
40
41
|
this._data = trimmed;
|
|
42
|
+
this._dataUint8 = new Uint8Array(this._data);
|
|
43
|
+
this._dataFloat32 = new Float32Array(this._data);
|
|
44
|
+
this._dataView = new DataView(this._data);
|
|
41
45
|
}
|
|
42
46
|
data() {
|
|
43
47
|
return this._dataUint8;
|
|
@@ -45,6 +49,13 @@ class SequenceRecorder {
|
|
|
45
49
|
appendCameraFrame(c) {
|
|
46
50
|
if (!this._started)
|
|
47
51
|
return;
|
|
52
|
+
if (!c.data) {
|
|
53
|
+
if (this._hasLoggedUnsuppored)
|
|
54
|
+
return;
|
|
55
|
+
this._hasLoggedUnsuppored = true;
|
|
56
|
+
loglevel_1.zcerr("Unable to record frames from this camera source");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
48
59
|
if (c.data.byteLength !== (c.dataWidth * c.dataHeight)) {
|
|
49
60
|
loglevel_1.zcerr("Unable to record frame to sequence: greyscale array doesn't match dimensions");
|
|
50
61
|
return;
|
package/lib/sequencesource.d.ts
CHANGED
|
@@ -4,14 +4,20 @@ export declare class SequenceSource extends Source {
|
|
|
4
4
|
private _impl;
|
|
5
5
|
private _pipeline;
|
|
6
6
|
private _packetNumber;
|
|
7
|
+
private _motionUpdatesQueued;
|
|
8
|
+
private _motionUpdatesSent;
|
|
7
9
|
private _decoder;
|
|
10
|
+
private _minFrameGapMs;
|
|
11
|
+
private _lastUpdateTime;
|
|
8
12
|
static create(p: zappar_pipeline_t): zappar_sequence_source_t;
|
|
9
13
|
static get(m: zappar_sequence_source_t): SequenceSource | undefined;
|
|
10
14
|
constructor(_impl: zappar_sequence_source_t, _pipeline: zappar_pipeline_t);
|
|
11
15
|
loadFromMemory(data: ArrayBuffer): void;
|
|
12
|
-
|
|
16
|
+
maxPlaybackFpsSet(fps: number): void;
|
|
17
|
+
getFrame(currentlyProcessing: boolean): void;
|
|
13
18
|
destroy(): void;
|
|
14
19
|
start(): void;
|
|
15
20
|
pause(): void;
|
|
16
21
|
uploadGL(info: CameraFrameInfo): void;
|
|
22
|
+
private _submitMotionUpdates;
|
|
17
23
|
}
|
package/lib/sequencesource.js
CHANGED
|
@@ -14,6 +14,10 @@ class SequenceSource extends source_1.Source {
|
|
|
14
14
|
this._impl = _impl;
|
|
15
15
|
this._pipeline = _pipeline;
|
|
16
16
|
this._packetNumber = 0;
|
|
17
|
+
this._motionUpdatesQueued = 0;
|
|
18
|
+
this._motionUpdatesSent = 0;
|
|
19
|
+
this._minFrameGapMs = 0;
|
|
20
|
+
this._lastUpdateTime = 0;
|
|
17
21
|
}
|
|
18
22
|
static create(p) {
|
|
19
23
|
let ret = (latest++);
|
|
@@ -28,66 +32,68 @@ class SequenceSource extends source_1.Source {
|
|
|
28
32
|
try {
|
|
29
33
|
this._decoder = new sequencerecorder_1.SequenceDecoder(data);
|
|
30
34
|
this._packetNumber = 0;
|
|
35
|
+
this._lastUpdateTime = 0;
|
|
31
36
|
}
|
|
32
37
|
catch (err) {
|
|
33
38
|
loglevel_1.zcerr("Unable to decode sequence:", err);
|
|
34
39
|
}
|
|
35
40
|
}
|
|
41
|
+
maxPlaybackFpsSet(fps) {
|
|
42
|
+
if (fps <= 0) {
|
|
43
|
+
this._minFrameGapMs = 0;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this._minFrameGapMs = 1000.0 / fps;
|
|
47
|
+
}
|
|
36
48
|
getFrame(currentlyProcessing) {
|
|
37
49
|
let pipeline = pipeline_1.Pipeline.get(this._pipeline);
|
|
38
50
|
if (!pipeline)
|
|
39
51
|
return;
|
|
52
|
+
if (!this._decoder)
|
|
53
|
+
return;
|
|
54
|
+
this._submitMotionUpdates(pipeline);
|
|
55
|
+
if (this._motionUpdatesQueued > this._motionUpdatesSent)
|
|
56
|
+
return;
|
|
40
57
|
if (currentlyProcessing)
|
|
41
58
|
return;
|
|
42
|
-
|
|
59
|
+
let curTime = performance.now();
|
|
60
|
+
if (curTime < this._lastUpdateTime + this._minFrameGapMs)
|
|
43
61
|
return;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
break;
|
|
59
|
-
case sequencerecorder_1.SequenceRecorderPacketType.ATTITUDE_MATRIX:
|
|
60
|
-
pipeline.motionAttitudeMatrix(packet.attitude);
|
|
61
|
-
break;
|
|
62
|
-
case sequencerecorder_1.SequenceRecorderPacketType.CAMERA_FRAME:
|
|
63
|
-
{
|
|
64
|
-
let pixels = pipeline.cameraPixelArrays.pop();
|
|
65
|
-
while (pixels) {
|
|
66
|
-
if (pixels.byteLength === packet.greyscale.byteLength)
|
|
67
|
-
break;
|
|
68
|
-
pixels = pipeline.cameraPixelArrays.pop();
|
|
69
|
-
}
|
|
70
|
-
if (!pixels) {
|
|
71
|
-
pixels = new ArrayBuffer(packet.greyscale.byteLength);
|
|
72
|
-
}
|
|
73
|
-
(new Uint8Array(pixels)).set(packet.greyscale);
|
|
74
|
-
return {
|
|
75
|
-
data: pixels,
|
|
76
|
-
cameraSourceData: packet.greyscale,
|
|
77
|
-
cameraModel: packet.cameraModel,
|
|
78
|
-
cameraToDevice: packet.cameraToDevice,
|
|
79
|
-
dataWidth: packet.width,
|
|
80
|
-
dataHeight: packet.height,
|
|
81
|
-
texture: undefined,
|
|
82
|
-
userFacing: packet.userFacing,
|
|
83
|
-
uvTransform: gl_matrix_1.mat4.create(),
|
|
84
|
-
cameraSource: this
|
|
85
|
-
};
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
62
|
+
if (this._packetNumber >= this._decoder.numberPackets)
|
|
63
|
+
return;
|
|
64
|
+
let packet = this._decoder.dataByPacket.get(this._packetNumber);
|
|
65
|
+
if (packet.type != sequencerecorder_1.SequenceRecorderPacketType.CAMERA_FRAME)
|
|
66
|
+
return;
|
|
67
|
+
this._packetNumber++;
|
|
68
|
+
let pixels = pipeline.cameraPixelArrays.pop();
|
|
69
|
+
while (pixels) {
|
|
70
|
+
if (pixels.byteLength === packet.greyscale.byteLength)
|
|
71
|
+
break;
|
|
72
|
+
pixels = pipeline.cameraPixelArrays.pop();
|
|
73
|
+
}
|
|
74
|
+
if (!pixels) {
|
|
75
|
+
pixels = new ArrayBuffer(packet.greyscale.byteLength);
|
|
89
76
|
}
|
|
90
|
-
|
|
77
|
+
(new Uint8Array(pixels)).set(packet.greyscale);
|
|
78
|
+
this._lastUpdateTime = curTime;
|
|
79
|
+
let info = {
|
|
80
|
+
data: pixels,
|
|
81
|
+
cameraSourceData: packet.greyscale,
|
|
82
|
+
cameraModel: packet.cameraModel,
|
|
83
|
+
cameraToDevice: packet.cameraToDevice,
|
|
84
|
+
dataWidth: packet.width,
|
|
85
|
+
dataHeight: packet.height,
|
|
86
|
+
texture: undefined,
|
|
87
|
+
userFacing: packet.userFacing,
|
|
88
|
+
uvTransform: gl_matrix_1.mat4.create(),
|
|
89
|
+
cameraSource: this
|
|
90
|
+
};
|
|
91
|
+
// We can queue the motion updates for the follwing frame immediately
|
|
92
|
+
// as this camera frame will be sent immediately, but the next motion
|
|
93
|
+
// updates will be one frame later
|
|
94
|
+
this._submitMotionUpdates(pipeline);
|
|
95
|
+
const token = pipeline.registerToken(info);
|
|
96
|
+
pipeline.sendDataToWorker(info.data || new ArrayBuffer(0), token, info.dataWidth, info.dataHeight, info.userFacing, info.cameraToDevice, info.cameraModel);
|
|
91
97
|
}
|
|
92
98
|
destroy() {
|
|
93
99
|
byId.delete(this._impl);
|
|
@@ -124,5 +130,41 @@ class SequenceSource extends source_1.Source {
|
|
|
124
130
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, info.dataWidth, info.dataHeight, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, new Uint8Array(info.cameraSourceData));
|
|
125
131
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
126
132
|
}
|
|
133
|
+
_submitMotionUpdates(pipeline) {
|
|
134
|
+
let pendingMotionUpdate = false;
|
|
135
|
+
while (this._packetNumber < this._decoder.numberPackets) {
|
|
136
|
+
let packet = this._decoder.dataByPacket.get(this._packetNumber);
|
|
137
|
+
if (packet.type == sequencerecorder_1.SequenceRecorderPacketType.CAMERA_FRAME)
|
|
138
|
+
break;
|
|
139
|
+
switch (packet.type) {
|
|
140
|
+
case sequencerecorder_1.SequenceRecorderPacketType.ACCELEROMETER:
|
|
141
|
+
pipeline.motionAccelerometerSubmit(packet.t, packet.x, packet.y, packet.z);
|
|
142
|
+
pendingMotionUpdate = true;
|
|
143
|
+
break;
|
|
144
|
+
case sequencerecorder_1.SequenceRecorderPacketType.ROTATION_RATE:
|
|
145
|
+
pipeline.motionRotationRateSubmit(packet.t, packet.x, packet.y, packet.z);
|
|
146
|
+
pendingMotionUpdate = true;
|
|
147
|
+
break;
|
|
148
|
+
case sequencerecorder_1.SequenceRecorderPacketType.ATTITUDE:
|
|
149
|
+
pipeline.motionAttitudeSubmit(packet.t, packet.x, packet.y, packet.z);
|
|
150
|
+
pendingMotionUpdate = true;
|
|
151
|
+
break;
|
|
152
|
+
case sequencerecorder_1.SequenceRecorderPacketType.ATTITUDE_MATRIX:
|
|
153
|
+
pipeline.motionAttitudeMatrix(packet.attitude);
|
|
154
|
+
pendingMotionUpdate = true;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
this._packetNumber++;
|
|
158
|
+
}
|
|
159
|
+
// If we've submitted motion updates, add a setTimeout to reflect when
|
|
160
|
+
// the message serializer will actually have sent them over to the worker
|
|
161
|
+
if (pendingMotionUpdate) {
|
|
162
|
+
this._motionUpdatesQueued++;
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
this._motionUpdatesSent++;
|
|
165
|
+
}, 0);
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
127
169
|
}
|
|
128
170
|
exports.SequenceSource = SequenceSource;
|
package/lib/source.d.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
/// <reference types="dom-webcodecs" />
|
|
1
2
|
export interface CameraFrameInfo {
|
|
2
|
-
data
|
|
3
|
+
data?: ArrayBuffer;
|
|
3
4
|
texture: WebGLTexture | undefined;
|
|
4
5
|
dataWidth: number;
|
|
5
6
|
dataHeight: number;
|
|
6
7
|
cameraModel: Float32Array;
|
|
7
8
|
cameraToDevice: Float32Array;
|
|
8
|
-
uvTransform: Float32Array;
|
|
9
|
-
userFacing: boolean;
|
|
10
9
|
cameraSource: Source;
|
|
11
10
|
cameraSourceData?: any;
|
|
11
|
+
uvTransform?: Float32Array;
|
|
12
|
+
userFacing: boolean;
|
|
13
|
+
frame?: VideoFrame | ImageBitmap;
|
|
12
14
|
}
|
|
13
15
|
export declare abstract class Source {
|
|
14
|
-
abstract getFrame(currentlyProcessing: boolean):
|
|
16
|
+
abstract getFrame(currentlyProcessing: boolean): void;
|
|
15
17
|
abstract pause(): void;
|
|
16
18
|
abstract uploadGL(info: CameraFrameInfo): void;
|
|
17
19
|
}
|
package/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.4.0-beta.
|
|
1
|
+
export declare const VERSION = "0.4.0-beta.7";
|
package/lib/version.js
CHANGED
package/lib/worker-client.js
CHANGED
|
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.launchWorker = exports.messageManager = void 0;
|
|
13
|
-
const bundleworker_mainthread_1 = require("./bundleworker-mainthread");
|
|
14
13
|
const messages_1 = require("./messages");
|
|
15
14
|
exports.messageManager = new messages_1.MsgManager();
|
|
16
15
|
let Worker;
|
|
@@ -29,10 +28,6 @@ function launchWorker() {
|
|
|
29
28
|
t: "wasm",
|
|
30
29
|
url: require("./zcv.wasm").default
|
|
31
30
|
});
|
|
32
|
-
worker.postMessage({
|
|
33
|
-
t: "port",
|
|
34
|
-
port: bundleworker_mainthread_1.bundleWorkerMessageChannel.port1
|
|
35
|
-
}, [bundleworker_mainthread_1.bundleWorkerMessageChannel.port1]);
|
|
36
31
|
yield waitForLoad(worker);
|
|
37
32
|
function sendOutgoing() {
|
|
38
33
|
let msgs = exports.messageManager.getOutgoingMessages();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { zappar_cwrap } from "./gen/zappar-native";
|
|
2
|
+
import { zappar_server } from "./gen/zappar-server";
|
|
3
|
+
import { MsgManager } from "./messages";
|
|
4
|
+
import { ImageBitmapC2S } from "./workerinterface";
|
|
5
|
+
export declare function handleImageBitmap(m: ImageBitmapC2S, r: zappar_cwrap, server: zappar_server, mgr: MsgManager): void;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleImageBitmap = void 0;
|
|
4
|
+
const image_process_gl_1 = require("./image-process-gl");
|
|
5
|
+
const profile_1 = require("./profile");
|
|
6
|
+
const gl_matrix_1 = require("gl-matrix");
|
|
7
|
+
let pixels;
|
|
8
|
+
let texture;
|
|
9
|
+
let _imageProcessor;
|
|
10
|
+
let _gl;
|
|
11
|
+
function getImageProcessor() {
|
|
12
|
+
if (!_imageProcessor || !_gl) {
|
|
13
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
14
|
+
_gl = canvas.getContext("webgl");
|
|
15
|
+
if (!_gl)
|
|
16
|
+
throw new Error("Unable to get offscreen GL context");
|
|
17
|
+
_imageProcessor = new image_process_gl_1.ImageProcessGL(_gl);
|
|
18
|
+
}
|
|
19
|
+
return [_imageProcessor, _gl];
|
|
20
|
+
}
|
|
21
|
+
function handleImageBitmap(m, r, server, mgr) {
|
|
22
|
+
// img: ImageBitmap,
|
|
23
|
+
// rot: number,
|
|
24
|
+
// tokenId: number,
|
|
25
|
+
// r: zappar_cwrap,
|
|
26
|
+
// p: zappar_pipeline_t,
|
|
27
|
+
// userFacing: boolean,
|
|
28
|
+
// server: zappar_server,
|
|
29
|
+
// mgr: MsgManager) {
|
|
30
|
+
const [imageProcessor, gl] = getImageProcessor();
|
|
31
|
+
if (!texture) {
|
|
32
|
+
texture = gl.createTexture();
|
|
33
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
34
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
35
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
36
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
37
|
+
}
|
|
38
|
+
if (!texture)
|
|
39
|
+
return;
|
|
40
|
+
if (!pixels || pixels.byteLength < profile_1.profile.dataWidth * profile_1.profile.dataHeight) {
|
|
41
|
+
console.log("Generating pixel buffer", profile_1.profile.dataWidth * profile_1.profile.dataHeight);
|
|
42
|
+
pixels = new ArrayBuffer(profile_1.profile.dataWidth * profile_1.profile.dataHeight);
|
|
43
|
+
}
|
|
44
|
+
imageProcessor.uploadFrame(texture, m.i, m.r, m.userFacing);
|
|
45
|
+
let info = imageProcessor.readFrame(texture, pixels);
|
|
46
|
+
let msg = {
|
|
47
|
+
t: "imageBitmapS2C",
|
|
48
|
+
dataWidth: info.dataWidth,
|
|
49
|
+
dataHeight: info.dataHeight,
|
|
50
|
+
frame: m.i,
|
|
51
|
+
userFacing: info.userFacing,
|
|
52
|
+
uvTransform: info.uvTransform || gl_matrix_1.mat4.create(),
|
|
53
|
+
tokenId: m.tokenId, p: m.p
|
|
54
|
+
};
|
|
55
|
+
mgr.postOutgoingMessage(msg, [m.i]);
|
|
56
|
+
let pipeline = server._pipeline_by_instance.get(m.p);
|
|
57
|
+
if (pipeline) {
|
|
58
|
+
r.pipeline_camera_frame_submit(pipeline, pixels, info.dataWidth, info.dataHeight, m.tokenId, m.cameraToDevice, m.cameraModel, info.userFacing);
|
|
59
|
+
r.pipeline_frame_update(pipeline);
|
|
60
|
+
server.exploreState();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.handleImageBitmap = handleImageBitmap;
|
package/lib/worker-server.d.ts
CHANGED
package/lib/worker-server.js
CHANGED
|
@@ -14,21 +14,12 @@ const ZNM = require("./zcv");
|
|
|
14
14
|
const zappar_cwrap_1 = require("./gen/zappar-cwrap");
|
|
15
15
|
const zappar_server_1 = require("./gen/zappar-server");
|
|
16
16
|
const messages_1 = require("./messages");
|
|
17
|
+
const gl_matrix_1 = require("gl-matrix");
|
|
18
|
+
const zappar_native_1 = require("./gen/zappar-native");
|
|
19
|
+
const worker_imagebitmap_1 = require("./worker-imagebitmap");
|
|
20
|
+
const profile_1 = require("./profile");
|
|
17
21
|
exports.messageManager = new messages_1.MsgManager();
|
|
18
|
-
let
|
|
19
|
-
self.addEventListener("message", msg => {
|
|
20
|
-
if (msg && msg.data && msg.data.t === "port") {
|
|
21
|
-
bundleWorkerPort = msg.data.port;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
self.bundle_adjust_message = function (buf) {
|
|
25
|
-
var buf_copy = new ArrayBuffer(buf.byteLength);
|
|
26
|
-
new Uint8Array(buf_copy).set(new Uint8Array(buf));
|
|
27
|
-
bundleWorkerPort === null || bundleWorkerPort === void 0 ? void 0 : bundleWorkerPort.postMessage({
|
|
28
|
-
t: "bundle_adjust_message",
|
|
29
|
-
buf: buf_copy
|
|
30
|
-
}, [buf_copy]);
|
|
31
|
-
};
|
|
22
|
+
let latestCameraToScreenRotation = 0;
|
|
32
23
|
function launchWorkerServer(wasmUrl) {
|
|
33
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
25
|
let mod = ZNM.default({
|
|
@@ -48,15 +39,6 @@ function launchWorkerServer(wasmUrl) {
|
|
|
48
39
|
}, [ab]);
|
|
49
40
|
});
|
|
50
41
|
exports.messageManager.postOutgoingMessage("loaded", []);
|
|
51
|
-
bundleWorkerPort.onmessage = function (msg) {
|
|
52
|
-
// Received message from other worker
|
|
53
|
-
var a_buf = msg.data.buf;
|
|
54
|
-
var buf = mod._malloc(a_buf.byteLength);
|
|
55
|
-
mod.HEAPU8.set(new Uint8Array(a_buf), buf);
|
|
56
|
-
/// call the exported native function to update the world map
|
|
57
|
-
mod._bundle_adjust_message_callback(buf, msg.data.buf.byteLength, 0);
|
|
58
|
-
mod._free(buf);
|
|
59
|
-
};
|
|
60
42
|
exports.messageManager.onIncomingMessage.bind((msg) => {
|
|
61
43
|
var _a;
|
|
62
44
|
switch (msg.t) {
|
|
@@ -67,7 +49,7 @@ function launchWorkerServer(wasmUrl) {
|
|
|
67
49
|
case "buf":
|
|
68
50
|
(_a = server.serializersByPipelineId.get(msg.p)) === null || _a === void 0 ? void 0 : _a.bufferReturn(msg.d);
|
|
69
51
|
break;
|
|
70
|
-
case "cameraFrameC2S":
|
|
52
|
+
case "cameraFrameC2S": {
|
|
71
53
|
let msgt = msg;
|
|
72
54
|
let pipeline = server._pipeline_by_instance.get(msgt.p);
|
|
73
55
|
let att;
|
|
@@ -86,6 +68,22 @@ function launchWorkerServer(wasmUrl) {
|
|
|
86
68
|
};
|
|
87
69
|
exports.messageManager.postOutgoingMessage(ret, [msgt.d]);
|
|
88
70
|
break;
|
|
71
|
+
}
|
|
72
|
+
case "streamC2S": {
|
|
73
|
+
let msgt = msg;
|
|
74
|
+
consumeStream(mod, r, msgt.s, msgt.p, msgt.userFacing, server, msgt.source);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "cameraToScreenC2S": {
|
|
78
|
+
let msgt = msg;
|
|
79
|
+
latestCameraToScreenRotation = msgt.r;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "imageBitmapC2S": {
|
|
83
|
+
let msgt = msg;
|
|
84
|
+
worker_imagebitmap_1.handleImageBitmap(msgt, r, server, exports.messageManager);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
89
87
|
}
|
|
90
88
|
});
|
|
91
89
|
}
|
|
@@ -94,3 +92,101 @@ function launchWorkerServer(wasmUrl) {
|
|
|
94
92
|
}
|
|
95
93
|
exports.launchWorkerServer = launchWorkerServer;
|
|
96
94
|
;
|
|
95
|
+
let streamDataBufferPointer = 0;
|
|
96
|
+
let streamDataBufferLength = 0;
|
|
97
|
+
let tokenId = 1;
|
|
98
|
+
const cameraToDeviceTransform = gl_matrix_1.mat4.create();
|
|
99
|
+
const cameraModel = new Float32Array([300, 300, 160, 120, 0, 0]);
|
|
100
|
+
function consumeStream(mod, r, stream, p, userFacing, server, source) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
const reader = yield stream.getReader();
|
|
103
|
+
while (true) {
|
|
104
|
+
let result = yield reader.read();
|
|
105
|
+
if (result.done) {
|
|
106
|
+
console.log("Stream done");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
let frame = result.value;
|
|
110
|
+
let size = frame.allocationSize();
|
|
111
|
+
if (size > streamDataBufferLength) {
|
|
112
|
+
if (streamDataBufferPointer > 0)
|
|
113
|
+
mod._free(streamDataBufferPointer);
|
|
114
|
+
streamDataBufferPointer = mod._malloc(size);
|
|
115
|
+
streamDataBufferLength = size;
|
|
116
|
+
}
|
|
117
|
+
yield frame.copyTo(mod.HEAPU8.subarray(streamDataBufferPointer, streamDataBufferPointer + streamDataBufferLength));
|
|
118
|
+
let token = tokenId;
|
|
119
|
+
tokenId++;
|
|
120
|
+
const width = frame.visibleRect.width;
|
|
121
|
+
const height = frame.visibleRect.height;
|
|
122
|
+
let uvTransform;
|
|
123
|
+
let dataWidth = width;
|
|
124
|
+
let dataHeight = height;
|
|
125
|
+
switch (latestCameraToScreenRotation) {
|
|
126
|
+
case 270:
|
|
127
|
+
uvTransform = new Float32Array([0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1]);
|
|
128
|
+
dataWidth = height;
|
|
129
|
+
dataHeight = width;
|
|
130
|
+
break;
|
|
131
|
+
case 180:
|
|
132
|
+
uvTransform = new Float32Array([-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1]);
|
|
133
|
+
break;
|
|
134
|
+
case 90:
|
|
135
|
+
uvTransform = new Float32Array([0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1]);
|
|
136
|
+
dataWidth = height;
|
|
137
|
+
dataHeight = width;
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
uvTransform = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
let clone = frame.clone();
|
|
144
|
+
if (userFacing)
|
|
145
|
+
gl_matrix_1.mat4.fromScaling(cameraToDeviceTransform, [-1, 1, -1]);
|
|
146
|
+
else
|
|
147
|
+
gl_matrix_1.mat4.identity(cameraToDeviceTransform);
|
|
148
|
+
let focalLength = 300.0 * profile_1.profile.dataWidth / 320.0;
|
|
149
|
+
cameraModel[0] = focalLength;
|
|
150
|
+
cameraModel[1] = focalLength;
|
|
151
|
+
cameraModel[2] = profile_1.profile.dataWidth * 0.5;
|
|
152
|
+
cameraModel[3] = profile_1.profile.dataHeight * 0.5;
|
|
153
|
+
const ret = {
|
|
154
|
+
token: token,
|
|
155
|
+
d: clone,
|
|
156
|
+
p: p,
|
|
157
|
+
t: "videoFrameS2C",
|
|
158
|
+
userFacing,
|
|
159
|
+
uvTransform,
|
|
160
|
+
w: dataWidth,
|
|
161
|
+
h: dataHeight,
|
|
162
|
+
cameraToDevice: cameraToDeviceTransform,
|
|
163
|
+
cameraModel,
|
|
164
|
+
source
|
|
165
|
+
};
|
|
166
|
+
exports.messageManager.postOutgoingMessage(ret, [ret.d, ret.uvTransform.buffer]);
|
|
167
|
+
const pipeline = server._pipeline_by_instance.get(p);
|
|
168
|
+
if (pipeline) {
|
|
169
|
+
r.pipeline_camera_frame_submit_raw_pointer(pipeline, streamDataBufferPointer, size, framePixelFormatFromFormat(frame.format), width, height, token, cameraToDeviceTransform, latestCameraToScreenRotation, cameraModel, userFacing);
|
|
170
|
+
r.pipeline_frame_update(pipeline);
|
|
171
|
+
server.exploreState();
|
|
172
|
+
}
|
|
173
|
+
frame.close();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function framePixelFormatFromFormat(f) {
|
|
178
|
+
switch (f) {
|
|
179
|
+
case "I420": return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_I420;
|
|
180
|
+
case "I420A": return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_I420A;
|
|
181
|
+
case "I422": return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_I422;
|
|
182
|
+
case "I444": return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_I444;
|
|
183
|
+
case "NV12": return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_NV12;
|
|
184
|
+
case "RGBA":
|
|
185
|
+
case "RGBX":
|
|
186
|
+
return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_RGBA;
|
|
187
|
+
case "BGRA":
|
|
188
|
+
case "BGRX":
|
|
189
|
+
return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_BGRA;
|
|
190
|
+
}
|
|
191
|
+
return zappar_native_1.frame_pixel_format_t.FRAME_PIXEL_FORMAT_Y;
|
|
192
|
+
}
|