@zappar/zappar-cv 0.4.0-beta.1 → 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.
Files changed (55) hide show
  1. package/CHANGELOG.md +79 -34
  2. package/README.md +2 -2
  3. package/lib/camera-source-map.d.ts +10 -0
  4. package/lib/camera-source-map.js +40 -0
  5. package/lib/camera-source.d.ts +2 -5
  6. package/lib/camera-source.js +3 -13
  7. package/lib/compatibility.js +1 -1
  8. package/lib/drawcamera.js +2 -1
  9. package/lib/gen/zappar-client.js +6 -1
  10. package/lib/gen/zappar-cwrap.js +37 -21
  11. package/lib/gen/zappar-native.d.ts +11 -0
  12. package/lib/gen/zappar-native.js +13 -1
  13. package/lib/gen/zappar-server.js +1 -1
  14. package/lib/gen/zappar.d.ts +5 -0
  15. package/lib/gen/zappar.js +5 -3
  16. package/lib/gfx.d.ts +1 -0
  17. package/lib/gfx.js +4 -0
  18. package/lib/html-element-source.d.ts +3 -20
  19. package/lib/html-element-source.js +19 -263
  20. package/lib/image-process-gl.d.ts +37 -0
  21. package/lib/image-process-gl.js +265 -0
  22. package/lib/imagebitmap-camera-source.d.ts +36 -0
  23. package/lib/imagebitmap-camera-source.js +277 -0
  24. package/lib/index.d.ts +1 -1
  25. package/lib/mstp-camera-source.d.ts +29 -0
  26. package/lib/mstp-camera-source.js +230 -0
  27. package/lib/native.js +45 -8
  28. package/lib/pipeline.d.ts +13 -3
  29. package/lib/pipeline.js +95 -26
  30. package/lib/profile.d.ts +2 -0
  31. package/lib/profile.js +55 -44
  32. package/lib/sequencerecorder.d.ts +1 -0
  33. package/lib/sequencerecorder.js +11 -0
  34. package/lib/sequencesource.d.ts +7 -1
  35. package/lib/sequencesource.js +89 -47
  36. package/lib/source.d.ts +6 -4
  37. package/lib/version.d.ts +1 -1
  38. package/lib/version.js +1 -1
  39. package/lib/worker-client.js +0 -5
  40. package/lib/worker-imagebitmap.d.ts +5 -0
  41. package/lib/worker-imagebitmap.js +63 -0
  42. package/lib/worker-server.d.ts +0 -5
  43. package/lib/worker-server.js +120 -30
  44. package/lib/workerinterface.d.ts +47 -1
  45. package/lib/zcv.js +23 -23
  46. package/lib/zcv.wasm +0 -0
  47. package/package.json +34 -31
  48. package/umd/{a20150d17b0290cadaa6cb9911ab9500.wasm → 9d9c4b542b40c41e3ef7587fb91e5d38.wasm} +0 -0
  49. package/umd/zappar-cv.js +1 -9
  50. package/umd/zappar-cv.worker.js +1 -1
  51. package/lib/bundleworker-mainthread.d.ts +0 -2
  52. package/lib/bundleworker-mainthread.js +0 -36
  53. package/lib/bundleworker-worker.d.ts +0 -3
  54. package/lib/bundleworker-worker.js +0 -47
  55. package/umd/5dd5cacd27e6e7da828f.bundleworker.js +0 -1
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MSTPCameraSource = void 0;
13
+ const profile_1 = require("./profile");
14
+ const pipeline_1 = require("./pipeline");
15
+ const source_1 = require("./source");
16
+ const cameramodel_1 = require("./cameramodel");
17
+ const loglevel_1 = require("./loglevel");
18
+ const camera_source_map_1 = require("./camera-source-map");
19
+ class MSTPCameraSource extends source_1.Source {
20
+ constructor(_impl, _pipeline, _deviceId) {
21
+ super();
22
+ this._impl = _impl;
23
+ this._pipeline = _pipeline;
24
+ this._deviceId = _deviceId;
25
+ this._currentStream = null;
26
+ this._activeDeviceId = null;
27
+ this._isPaused = true;
28
+ this._isUserFacing = false;
29
+ this._cameraToScreenRotation = 0;
30
+ this._hasStartedOrientation = false;
31
+ this._deviceMotionListener = (ev) => {
32
+ let pipeline = pipeline_1.Pipeline.get(this._pipeline);
33
+ if (!pipeline)
34
+ return;
35
+ let timeStamp = (ev.timeStamp !== undefined && ev.timeStamp !== null) ? ev.timeStamp : performance.now();
36
+ if (ev.accelerationIncludingGravity !== null &&
37
+ ev.accelerationIncludingGravity.x !== null &&
38
+ ev.accelerationIncludingGravity.y !== null &&
39
+ ev.accelerationIncludingGravity.z !== null) {
40
+ pipeline.motionAccelerometerSubmit(timeStamp, ev.accelerationIncludingGravity.x * profile_1.profile.deviceMotionMutliplier, ev.accelerationIncludingGravity.y * profile_1.profile.deviceMotionMutliplier, ev.accelerationIncludingGravity.z * profile_1.profile.deviceMotionMutliplier);
41
+ }
42
+ if (ev.rotationRate !== null &&
43
+ ev.rotationRate.alpha !== null &&
44
+ ev.rotationRate.beta !== null &&
45
+ ev.rotationRate.gamma !== null && !this._hasStartedOrientation) {
46
+ ev.timeStamp;
47
+ pipeline.motionRotationRateSubmit(timeStamp, ev.rotationRate.alpha * Math.PI / -180.0, ev.rotationRate.beta * Math.PI / -180.0, ev.rotationRate.gamma * Math.PI / -180.0);
48
+ }
49
+ else if (!this._hasStartedOrientation) {
50
+ this._startDeviceOrientation();
51
+ }
52
+ };
53
+ loglevel_1.zcout("Using MSTP camera source");
54
+ }
55
+ destroy() {
56
+ this.pause();
57
+ camera_source_map_1.deleteCameraSource(this._impl);
58
+ }
59
+ _stop() {
60
+ if (!this._currentStream)
61
+ return;
62
+ let tracks = this._currentStream.getTracks();
63
+ tracks.forEach(t => t.stop());
64
+ this._currentStream = null;
65
+ }
66
+ pause() {
67
+ this._isPaused = true;
68
+ let p = pipeline_1.Pipeline.get(this._pipeline);
69
+ if (p && p.currentCameraSource === this)
70
+ p.currentCameraSource = undefined;
71
+ this._stopDeviceMotion();
72
+ this._syncCamera();
73
+ }
74
+ start() {
75
+ var _a;
76
+ let p = pipeline_1.Pipeline.get(this._pipeline);
77
+ if (p && p.currentCameraSource !== this) {
78
+ (_a = p.currentCameraSource) === null || _a === void 0 ? void 0 : _a.pause();
79
+ p.currentCameraSource = this;
80
+ }
81
+ this._isPaused = false;
82
+ this._startDeviceMotion();
83
+ this._syncCamera();
84
+ }
85
+ _getConstraints() {
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ let deviceId;
88
+ let facingMode;
89
+ if (this._deviceId !== MSTPCameraSource.DEFAULT_DEVICE_ID &&
90
+ this._deviceId !== MSTPCameraSource.USER_DEFAULT_DEVICE_ID) {
91
+ // Custom device
92
+ deviceId = this._deviceId;
93
+ }
94
+ else {
95
+ facingMode = (this._deviceId === MSTPCameraSource.DEFAULT_DEVICE_ID) ? "environment" : "user";
96
+ }
97
+ let constraints = {
98
+ audio: false,
99
+ video: {
100
+ facingMode: facingMode,
101
+ width: profile_1.profile.videoWidth,
102
+ height: profile_1.profile.videoHeight,
103
+ frameRate: profile_1.profile.requestHighFrameRate ? 60 : undefined,
104
+ deviceId: deviceId
105
+ }
106
+ };
107
+ if (deviceId)
108
+ return constraints;
109
+ if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices)
110
+ return constraints;
111
+ let devices = yield navigator.mediaDevices.enumerateDevices();
112
+ let hasHadCapabilities = false;
113
+ devices = devices.filter(val => {
114
+ // Remove non-video devices
115
+ if (val.kind !== "videoinput")
116
+ return false;
117
+ // If the media info object contains capabilities, use it to filter to the correct facing cameras
118
+ if (val.getCapabilities) {
119
+ hasHadCapabilities = true;
120
+ let capabilities = val.getCapabilities();
121
+ if (capabilities && capabilities.facingMode && capabilities.facingMode.indexOf(facingMode === "user" ? "user" : "environment") < 0)
122
+ return false;
123
+ }
124
+ return true;
125
+ });
126
+ // If none of the devices had capability info, or we have no devices left, fall back to the standard constraints
127
+ if (!hasHadCapabilities || devices.length === 0) {
128
+ return constraints;
129
+ }
130
+ if (typeof constraints.video === "object") {
131
+ loglevel_1.zcout("choosing device ID", devices[devices.length - 1].deviceId);
132
+ constraints.video.deviceId = devices[devices.length - 1].deviceId;
133
+ }
134
+ return constraints;
135
+ });
136
+ }
137
+ getFrame(allowRead) {
138
+ var _a, _b;
139
+ let rotation = cameramodel_1.cameraRotationForScreenOrientation(false);
140
+ if (rotation != this._cameraToScreenRotation) {
141
+ (_b = (_a = pipeline_1.Pipeline.get(this._pipeline)) === null || _a === void 0 ? void 0 : _a.sendCameraToScreenRotationToWorker) === null || _b === void 0 ? void 0 : _b.call(_a, rotation);
142
+ this._cameraToScreenRotation = rotation;
143
+ }
144
+ return;
145
+ }
146
+ _getUserMedia() {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ let constraints = yield this._getConstraints();
149
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia)
150
+ return yield navigator.mediaDevices.getUserMedia(constraints);
151
+ return yield new Promise((resolve, reject) => {
152
+ navigator.getUserMedia(constraints, resolve, reject);
153
+ });
154
+ });
155
+ }
156
+ _syncCamera() {
157
+ return __awaiter(this, void 0, void 0, function* () {
158
+ if (this._currentStream && this._isPaused) {
159
+ this._stop();
160
+ return;
161
+ }
162
+ if (this._currentStream && this._activeDeviceId !== this._deviceId)
163
+ this._stop();
164
+ if (!this._isPaused) {
165
+ this._activeDeviceId = this._deviceId;
166
+ this._currentStream = yield this._getUserMedia();
167
+ if (this._isPaused) {
168
+ yield this._syncCamera();
169
+ return;
170
+ }
171
+ this._isUserFacing = false;
172
+ if (this._currentStream) {
173
+ let videoTracks = this._currentStream.getVideoTracks();
174
+ if (videoTracks.length > 0) {
175
+ this._isUserFacing = videoTracks[0].getSettings().facingMode === "user";
176
+ let processor = new MediaStreamTrackProcessor({
177
+ track: videoTracks[0]
178
+ });
179
+ let p = pipeline_1.Pipeline.get(this._pipeline);
180
+ if (p)
181
+ p.sendCameraStreamToWorker(this._impl, processor.readable, this._isUserFacing);
182
+ }
183
+ }
184
+ }
185
+ });
186
+ }
187
+ _startDeviceOrientation() {
188
+ if (this._hasStartedOrientation)
189
+ return;
190
+ this._hasStartedOrientation = true;
191
+ window.addEventListener("deviceorientation", (ev) => {
192
+ let pipeline = pipeline_1.Pipeline.get(this._pipeline);
193
+ if (!pipeline)
194
+ return;
195
+ let timeStamp = (ev.timeStamp !== undefined && ev.timeStamp !== null) ? ev.timeStamp : performance.now();
196
+ if (ev.alpha === null || ev.beta === null || ev.gamma === null)
197
+ return;
198
+ pipeline.motionAttitudeSubmit(timeStamp, ev.alpha, ev.beta, ev.gamma);
199
+ });
200
+ }
201
+ _startDeviceMotion() {
202
+ window.addEventListener("devicemotion", this._deviceMotionListener, false);
203
+ }
204
+ _stopDeviceMotion() {
205
+ window.removeEventListener("devicemotion", this._deviceMotionListener);
206
+ }
207
+ uploadGL(info) {
208
+ const pipeline = pipeline_1.Pipeline.get(this._pipeline);
209
+ const gl = pipeline === null || pipeline === void 0 ? void 0 : pipeline.glContext;
210
+ if (!info ||
211
+ info.texture ||
212
+ !info.frame ||
213
+ !pipeline ||
214
+ !gl)
215
+ return;
216
+ let texture = pipeline.getVideoTexture();
217
+ if (!texture)
218
+ return;
219
+ gl.bindTexture(gl.TEXTURE_2D, texture);
220
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
221
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, info.frame);
222
+ gl.bindTexture(gl.TEXTURE_2D, null);
223
+ info.texture = texture;
224
+ info.frame.close();
225
+ delete info.frame;
226
+ }
227
+ }
228
+ exports.MSTPCameraSource = MSTPCameraSource;
229
+ MSTPCameraSource.USER_DEFAULT_DEVICE_ID = "Simulated User Default Device ID: a908df7f-5661-4d20-b227-a1c15d2fdb4b";
230
+ MSTPCameraSource.DEFAULT_DEVICE_ID = "Simulated Default Device ID: a908df7f-5661-4d20-b227-a1c15d2fdb4b";
package/lib/native.js CHANGED
@@ -24,13 +24,17 @@ const facelandmark_1 = require("./facelandmark");
24
24
  const compatibility_1 = require("./compatibility");
25
25
  const loglevel_1 = require("./loglevel");
26
26
  const sequencesource_1 = require("./sequencesource");
27
- // import { launchBundleWorker } from "./bundleworker-mainthread";
27
+ const camera_source_map_1 = require("./camera-source-map");
28
+ const gfx_1 = require("./gfx");
28
29
  let client;
29
30
  function initialize() {
30
31
  if (client)
31
32
  return client;
32
- worker_client_1.launchWorker();
33
- // launchBundleWorker();
33
+ let loaded = false;
34
+ worker_client_1.launchWorker().then(() => {
35
+ loglevel_1.zcout("Fully loaded");
36
+ loaded = true;
37
+ });
34
38
  let c = new zappar_client_1.zappar_client(ab => {
35
39
  worker_client_1.messageManager.postOutgoingMessage({
36
40
  t: "zappar",
@@ -43,7 +47,7 @@ function initialize() {
43
47
  c.impl.analytics_project_id_set(".wiz" + pathParts[1]);
44
48
  }
45
49
  worker_client_1.messageManager.onIncomingMessage.bind(msg => {
46
- var _a, _b;
50
+ var _a, _b, _c, _d, _e, _f, _g;
47
51
  switch (msg.t) {
48
52
  case "zappar":
49
53
  (_a = pipeline_1.Pipeline.get(msg.p)) === null || _a === void 0 ? void 0 : _a.pendingMessages.push(msg.d);
@@ -51,10 +55,21 @@ function initialize() {
51
55
  case "buf":
52
56
  c.serializer.bufferReturn(msg.d);
53
57
  break;
54
- case "cameraFrameRecycleS2C":
58
+ case "cameraFrameRecycleS2C": {
59
+ let msgt = msg;
60
+ (_c = (_b = pipeline_1.Pipeline.get(msgt.p)) === null || _b === void 0 ? void 0 : _b.cameraTokenReturn) === null || _c === void 0 ? void 0 : _c.call(_b, msg);
61
+ break;
62
+ }
63
+ case "videoFrameS2C": {
64
+ let msgt = msg;
65
+ (_e = (_d = pipeline_1.Pipeline.get(msgt.p)) === null || _d === void 0 ? void 0 : _d.videoFrameFromWorker) === null || _e === void 0 ? void 0 : _e.call(_d, msgt);
66
+ break;
67
+ }
68
+ case "imageBitmapS2C": {
55
69
  let msgt = msg;
56
- (_b = pipeline_1.Pipeline.get(msgt.p)) === null || _b === void 0 ? void 0 : _b.cameraTokenReturn(msgt);
70
+ (_g = (_f = pipeline_1.Pipeline.get(msgt.p)) === null || _f === void 0 ? void 0 : _f.imageBitmapFromWorker) === null || _g === void 0 ? void 0 : _g.call(_f, msgt);
57
71
  break;
72
+ }
58
73
  case "licerr": {
59
74
  let div = document.createElement("div");
60
75
  div.innerHTML = "Visit <a href='https://docs.zap.works/universal-ar/licensing/' style='color: white;'>our licensing page</a> to find out about hosting on your own domain.";
@@ -80,9 +95,31 @@ function initialize() {
80
95
  }, 1000);
81
96
  document.body.append(div);
82
97
  }
98
+ case "gfx": {
99
+ let div = document.createElement("div");
100
+ div.innerHTML = gfx_1.gfx;
101
+ div.style.position = "absolute";
102
+ div.style.bottom = "20px";
103
+ div.style.width = "250px";
104
+ div.style.left = "50%";
105
+ div.style.marginLeft = "-125px";
106
+ div.style.zIndex = Number.MAX_SAFE_INTEGER.toString();
107
+ div.style.opacity = "0";
108
+ div.style.transition = "opacity 0.5s";
109
+ document.body.append(div);
110
+ setTimeout(function () {
111
+ div.style.opacity = "1";
112
+ }, 500);
113
+ setTimeout(function () {
114
+ div.style.opacity = "0";
115
+ }, 3000);
116
+ setTimeout(function () {
117
+ div.remove();
118
+ }, 4000);
119
+ }
83
120
  }
84
121
  });
85
- client = Object.assign(Object.assign({}, c.impl), { camera_default_device_id: userFacing => userFacing ? camera_source_1.CameraSource.USER_DEFAULT_DEVICE_ID : camera_source_1.CameraSource.DEFAULT_DEVICE_ID, camera_source_create: (p, deviceId) => camera_source_1.CameraSource.create(p, deviceId), camera_source_destroy: cam => { var _a; return (_a = camera_source_1.CameraSource.get(cam)) === null || _a === void 0 ? void 0 : _a.destroy(); }, camera_source_pause: cam => { var _a; return (_a = camera_source_1.CameraSource.get(cam)) === null || _a === void 0 ? void 0 : _a.pause(); }, camera_source_start: cam => { var _a; return (_a = camera_source_1.CameraSource.get(cam)) === null || _a === void 0 ? void 0 : _a.start(); }, pipeline_create: () => pipeline_1.Pipeline.create(c.impl, worker_client_1.messageManager), pipeline_frame_update: (p) => { var _a; return (_a = pipeline_1.Pipeline.get(p)) === null || _a === void 0 ? void 0 : _a.frameUpdate(c); }, pipeline_camera_frame_draw_gl: (pipeline, screenWidth, screenHeight, mirror) => {
122
+ client = Object.assign(Object.assign({}, c.impl), { loaded: () => loaded, camera_default_device_id: userFacing => userFacing ? camera_source_1.CameraSource.USER_DEFAULT_DEVICE_ID : camera_source_1.CameraSource.DEFAULT_DEVICE_ID, camera_source_create: (p, deviceId) => camera_source_map_1.createCameraSource(p, deviceId), camera_source_destroy: cam => { var _a; return (_a = camera_source_map_1.getCameraSource(cam)) === null || _a === void 0 ? void 0 : _a.destroy(); }, camera_source_pause: cam => { var _a; return (_a = camera_source_map_1.getCameraSource(cam)) === null || _a === void 0 ? void 0 : _a.pause(); }, camera_source_start: cam => { var _a; return (_a = camera_source_map_1.getCameraSource(cam)) === null || _a === void 0 ? void 0 : _a.start(); }, pipeline_create: () => pipeline_1.Pipeline.create(c.impl, worker_client_1.messageManager), pipeline_frame_update: (p) => { var _a; return (_a = pipeline_1.Pipeline.get(p)) === null || _a === void 0 ? void 0 : _a.frameUpdate(c); }, pipeline_camera_frame_draw_gl: (pipeline, screenWidth, screenHeight, mirror) => {
86
123
  var _a;
87
124
  (_a = pipeline_1.Pipeline.get(pipeline)) === null || _a === void 0 ? void 0 : _a.cameraFrameDrawGL(screenWidth, screenHeight, mirror);
88
125
  }, draw_plane: (gl, projectionMatrix, cameraMatrix, targetMatrix, texture) => {
@@ -302,7 +339,7 @@ function initialize() {
302
339
  return gl_matrix_1.mat4.create();
303
340
  }
304
341
  return obj.anchor_pose;
305
- }, html_element_source_create: (pipeline, elm) => html_element_source_1.HTMLElementSource.createVideoElementSource(pipeline, elm), html_element_source_start: o => { var _a; return (_a = html_element_source_1.HTMLElementSource.getVideoElementSource(o)) === null || _a === void 0 ? void 0 : _a.start(); }, html_element_source_pause: o => { var _a; return (_a = html_element_source_1.HTMLElementSource.getVideoElementSource(o)) === null || _a === void 0 ? void 0 : _a.pause(); }, html_element_source_destroy: o => { var _a; return (_a = html_element_source_1.HTMLElementSource.getVideoElementSource(o)) === null || _a === void 0 ? void 0 : _a.destroy(); }, sequence_source_create: p => sequencesource_1.SequenceSource.create(p), sequence_source_load_from_memory: (o, data) => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.loadFromMemory(data); }, sequence_source_pause: o => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.pause(); }, sequence_source_start: o => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.start(); }, sequence_source_destroy: o => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.destroy(); }, permission_granted_all: permission_1.permissionGrantedAll, permission_granted_camera: permission_1.permissionGrantedCamera, permission_granted_motion: permission_1.permissionGrantedMotion, permission_denied_any: permission_1.permissionDeniedAny, permission_denied_camera: permission_1.permissionDeniedCamera, permission_denied_motion: permission_1.permissionDeniedMotion, permission_request_motion: permission_1.permissionRequestMotion, permission_request_camera: permission_1.permissionRequestCamera, permission_request_all: permission_1.permissionRequestAll, permission_request_ui: permission_1.permissionRequestUI, permission_request_ui_promise: permission_1.permissionRequestUI, permission_denied_ui: permission_1.permissionDeniedUI, browser_incompatible: compatibility_1.default.incompatible, browser_incompatible_ui: compatibility_1.default.incompatible_ui, log_level_set: l => {
342
+ }, html_element_source_create: (pipeline, elm) => html_element_source_1.HTMLElementSource.createVideoElementSource(pipeline, elm), html_element_source_start: o => { var _a; return (_a = html_element_source_1.HTMLElementSource.getVideoElementSource(o)) === null || _a === void 0 ? void 0 : _a.start(); }, html_element_source_pause: o => { var _a; return (_a = html_element_source_1.HTMLElementSource.getVideoElementSource(o)) === null || _a === void 0 ? void 0 : _a.pause(); }, html_element_source_destroy: o => { var _a; return (_a = html_element_source_1.HTMLElementSource.getVideoElementSource(o)) === null || _a === void 0 ? void 0 : _a.destroy(); }, sequence_source_create: p => sequencesource_1.SequenceSource.create(p), sequence_source_load_from_memory: (o, data) => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.loadFromMemory(data); }, sequence_source_pause: o => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.pause(); }, sequence_source_start: o => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.start(); }, sequence_source_max_playback_fps_set: (o, fps) => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.maxPlaybackFpsSet(fps); }, sequence_source_destroy: o => { var _a; return (_a = sequencesource_1.SequenceSource.get(o)) === null || _a === void 0 ? void 0 : _a.destroy(); }, permission_granted_all: permission_1.permissionGrantedAll, permission_granted_camera: permission_1.permissionGrantedCamera, permission_granted_motion: permission_1.permissionGrantedMotion, permission_denied_any: permission_1.permissionDeniedAny, permission_denied_camera: permission_1.permissionDeniedCamera, permission_denied_motion: permission_1.permissionDeniedMotion, permission_request_motion: permission_1.permissionRequestMotion, permission_request_camera: permission_1.permissionRequestCamera, permission_request_all: permission_1.permissionRequestAll, permission_request_ui: permission_1.permissionRequestUI, permission_request_ui_promise: permission_1.permissionRequestUI, permission_denied_ui: permission_1.permissionDeniedUI, browser_incompatible: compatibility_1.default.incompatible, browser_incompatible_ui: compatibility_1.default.incompatible_ui, log_level_set: l => {
306
343
  loglevel_1.setLogLevel(l);
307
344
  c.impl.log_level_set(l);
308
345
  } });
package/lib/pipeline.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { zappar_pipeline_t } from "./gen/zappar";
1
+ /// <reference types="dom-webcodecs" />
2
+ import { zappar_pipeline_t, zappar_camera_source_t } from "./gen/zappar";
2
3
  import { zappar_cwrap } from "./gen/zappar-native";
3
4
  import { zappar_client } from "./gen/zappar-client";
4
5
  import { MsgManager } from "./messages";
5
6
  import { mat4 } from "gl-matrix";
6
7
  import { Source, CameraFrameInfo } from "./source";
7
- import { CameraFrameReturnS2C } from "./workerinterface";
8
+ import { CameraFrameReturnS2C, ImageBitmapS2C, VideoFrameS2C } from "./workerinterface";
8
9
  import { FaceMesh } from "./facemesh";
9
10
  import { Event } from "./event";
10
11
  export declare class Pipeline {
@@ -24,11 +25,13 @@ export declare class Pipeline {
24
25
  private _faceProjectDraw;
25
26
  private _sequenceRecorder;
26
27
  private _sequenceRecordDeviceAttitudeMatrices;
28
+ private _sequenceRecorderFirstCameraToken;
27
29
  onGLContextReset: Event;
28
30
  static create(client: zappar_cwrap, mgr: MsgManager): zappar_pipeline_t;
29
31
  static get(p: zappar_pipeline_t): Pipeline | undefined;
30
32
  private constructor();
31
33
  frameUpdate(client: zappar_client): void;
34
+ cleanOldFrames(): void;
32
35
  cameraTokenReturn(msg: CameraFrameReturnS2C): void;
33
36
  sequenceRecordStart(expectedFrames: number): void;
34
37
  sequenceRecordStop(): void;
@@ -47,11 +50,18 @@ export declare class Pipeline {
47
50
  cameraFrameTextureMatrix(sw: number, sh: number, mirror: boolean): Float32Array;
48
51
  cameraFrameUserFacing(): boolean;
49
52
  cameraPoseWithAttitude(mirror: boolean): Float32Array;
53
+ videoFrameFromWorker(msg: VideoFrameS2C): void;
54
+ imageBitmapFromWorker(msg: ImageBitmapS2C): void;
55
+ uploadGL(): void;
56
+ registerToken(info: CameraFrameInfo): number;
50
57
  processGL(): void;
51
58
  motionAccelerometerSubmit(timestamp: number, x: number, y: number, z: number): void;
52
59
  motionRotationRateSubmit(timestamp: number, x: number, y: number, z: number): void;
53
60
  motionAttitudeSubmit(timestamp: number, x: number, y: number, z: number): void;
54
61
  motionAttitudeMatrix(m: Float32Array): void;
55
- uploadGL(): void;
62
+ sendCameraStreamToWorker(source: zappar_camera_source_t, stream: ReadableStream<VideoFrame>, userFacing: boolean): void;
63
+ sendCameraToScreenRotationToWorker(rot: number): void;
64
+ sendImageBitmapToWorker(img: ImageBitmap, rot: number, userFacing: boolean, tokenId: number, cameraModel: Float32Array, cameraToDevice: Float32Array): void;
65
+ sendDataToWorker(data: ArrayBuffer, token: number, width: number, height: number, userFacing: boolean, cameraToDevice: Float32Array, cameraModel: Float32Array): void;
56
66
  }
57
67
  export declare function applyScreenCounterRotation(info: CameraFrameInfo | undefined, inp: Float32Array): mat4;
package/lib/pipeline.js CHANGED
@@ -10,7 +10,9 @@ const drawplane_1 = require("./drawplane");
10
10
  const event_1 = require("./event");
11
11
  const loglevel_1 = require("./loglevel");
12
12
  const sequencerecorder_1 = require("./sequencerecorder");
13
+ const camera_source_map_1 = require("./camera-source-map");
13
14
  let byId = new Map();
15
+ let identity = gl_matrix_1.mat4.create();
14
16
  class Pipeline {
15
17
  constructor(_client, _impl, _mgr) {
16
18
  this._client = _client;
@@ -23,6 +25,7 @@ class Pipeline {
23
25
  this.videoTextures = [];
24
26
  this.cameraPixelArrays = [];
25
27
  this._sequenceRecordDeviceAttitudeMatrices = true;
28
+ this._sequenceRecorderFirstCameraToken = 0;
26
29
  this.onGLContextReset = new event_1.Event();
27
30
  }
28
31
  static create(client, mgr) {
@@ -43,6 +46,10 @@ class Pipeline {
43
46
  }, [msg]);
44
47
  }
45
48
  this.pendingMessages = [];
49
+ this.cleanOldFrames();
50
+ }
51
+ cleanOldFrames() {
52
+ var _a, _b;
46
53
  let currentToken = this._client.pipeline_camera_frame_user_data(this._impl);
47
54
  if (!currentToken)
48
55
  return;
@@ -50,12 +57,14 @@ class Pipeline {
50
57
  if (t[0] < currentToken) {
51
58
  if (t[1].texture)
52
59
  this.videoTextures.push(t[1].texture);
60
+ (_b = (_a = t[1].frame) === null || _a === void 0 ? void 0 : _a.close) === null || _b === void 0 ? void 0 : _b.call(_a);
53
61
  this.cameraTokens.delete(t[0]);
54
62
  }
55
63
  }
56
64
  }
57
65
  cameraTokenReturn(msg) {
58
- if (this._sequenceRecorder && this._sequenceRecordDeviceAttitudeMatrices) {
66
+ if (this._sequenceRecorder && this._sequenceRecordDeviceAttitudeMatrices
67
+ && msg.token >= this._sequenceRecorderFirstCameraToken) {
59
68
  let info = this.cameraTokens.get(msg.token);
60
69
  if (info) {
61
70
  if (msg.att)
@@ -71,6 +80,7 @@ class Pipeline {
71
80
  if (!this._sequenceRecorder)
72
81
  this._sequenceRecorder = new sequencerecorder_1.SequenceRecorder(expectedFrames);
73
82
  this._sequenceRecorder.start();
83
+ this._sequenceRecorderFirstCameraToken = this.nextCameraToken;
74
84
  }
75
85
  sequenceRecordStop() {
76
86
  var _a;
@@ -174,7 +184,7 @@ class Pipeline {
174
184
  let info = this.getCurrentCameraInfo();
175
185
  if (!info)
176
186
  return gl_matrix_1.mat4.create();
177
- return drawcamera_1.cameraFrameTextureMatrix(info.dataWidth, info.dataHeight, sw, sh, info.uvTransform, mirror);
187
+ return drawcamera_1.cameraFrameTextureMatrix(info.dataWidth, info.dataHeight, sw, sh, info.uvTransform || identity, mirror);
178
188
  }
179
189
  cameraFrameUserFacing() {
180
190
  var _a;
@@ -191,8 +201,48 @@ class Pipeline {
191
201
  gl_matrix_1.mat4.invert(res, res);
192
202
  return res;
193
203
  }
204
+ videoFrameFromWorker(msg) {
205
+ let tokenId = this.nextCameraToken++;
206
+ const cameraSource = camera_source_map_1.getCameraSource(msg.source);
207
+ if (!cameraSource)
208
+ return;
209
+ this.cameraTokens.set(tokenId, {
210
+ dataWidth: msg.w,
211
+ dataHeight: msg.h,
212
+ texture: undefined,
213
+ frame: msg.d,
214
+ userFacing: msg.userFacing,
215
+ uvTransform: msg.uvTransform,
216
+ cameraModel: msg.cameraModel,
217
+ cameraToDevice: msg.cameraToDevice,
218
+ cameraSource
219
+ });
220
+ this.cleanOldFrames();
221
+ }
222
+ imageBitmapFromWorker(msg) {
223
+ let data = this.cameraTokens.get(msg.tokenId);
224
+ if (!data)
225
+ return;
226
+ data.dataWidth = msg.dataWidth;
227
+ data.dataHeight = msg.dataHeight;
228
+ data.frame = msg.frame;
229
+ data.userFacing = msg.userFacing;
230
+ data.uvTransform = msg.uvTransform;
231
+ this.tokensInFlight--;
232
+ this.cleanOldFrames();
233
+ }
234
+ uploadGL() {
235
+ var _a, _b;
236
+ let info = this.getCurrentCameraInfo();
237
+ (_b = (_a = info === null || info === void 0 ? void 0 : info.cameraSource) === null || _a === void 0 ? void 0 : _a.uploadGL) === null || _b === void 0 ? void 0 : _b.call(_a, info);
238
+ }
239
+ registerToken(info) {
240
+ let tokenId = this.nextCameraToken++;
241
+ this.cameraTokens.set(tokenId, info);
242
+ this.tokensInFlight++;
243
+ return tokenId;
244
+ }
194
245
  processGL() {
195
- var _a;
196
246
  if (!this.glContext) {
197
247
  loglevel_1.zcerr("no GL context for camera frames - please call pipeline_gl_context_set");
198
248
  return;
@@ -203,26 +253,7 @@ class Pipeline {
203
253
  this.currentCameraSource.getFrame(true);
204
254
  return;
205
255
  }
206
- let info = this.currentCameraSource.getFrame(false);
207
- if (!info)
208
- return;
209
- let tokenId = this.nextCameraToken++;
210
- this.cameraTokens.set(tokenId, info);
211
- let msg = {
212
- d: info.data,
213
- p: this._impl,
214
- width: info.dataWidth,
215
- height: info.dataHeight,
216
- token: tokenId,
217
- userFacing: info.userFacing,
218
- c2d: info.cameraToDevice,
219
- cm: info.cameraModel,
220
- t: "cameraFrameC2S"
221
- };
222
- if (!this._sequenceRecordDeviceAttitudeMatrices)
223
- (_a = this._sequenceRecorder) === null || _a === void 0 ? void 0 : _a.appendCameraFrame(info);
224
- this.tokensInFlight++;
225
- this._mgr.postOutgoingMessage(msg, [info.data]);
256
+ this.currentCameraSource.getFrame(false);
226
257
  }
227
258
  motionAccelerometerSubmit(timestamp, x, y, z) {
228
259
  var _a;
@@ -246,9 +277,47 @@ class Pipeline {
246
277
  // This doesn't need to be added to the sequence since that's done on frame update instead
247
278
  this._client.pipeline_motion_attitude_matrix_submit(this._impl, m);
248
279
  }
249
- uploadGL() {
250
- let info = this.getCurrentCameraInfo();
251
- info === null || info === void 0 ? void 0 : info.cameraSource.uploadGL(info);
280
+ sendCameraStreamToWorker(source, stream, userFacing) {
281
+ let msg = {
282
+ t: "streamC2S",
283
+ p: this._impl,
284
+ s: stream,
285
+ userFacing,
286
+ source
287
+ };
288
+ this._mgr.postOutgoingMessage(msg, [msg.s]);
289
+ }
290
+ sendCameraToScreenRotationToWorker(rot) {
291
+ let msg = {
292
+ p: this._impl,
293
+ t: "cameraToScreenC2S",
294
+ r: rot
295
+ };
296
+ this._mgr.postOutgoingMessage(msg, []);
297
+ }
298
+ sendImageBitmapToWorker(img, rot, userFacing, tokenId, cameraModel, cameraToDevice) {
299
+ let msg = {
300
+ p: this._impl,
301
+ t: "imageBitmapC2S",
302
+ i: img,
303
+ r: rot,
304
+ tokenId,
305
+ userFacing,
306
+ cameraModel,
307
+ cameraToDevice
308
+ };
309
+ this._mgr.postOutgoingMessage(msg, [img]);
310
+ }
311
+ sendDataToWorker(data, token, width, height, userFacing, cameraToDevice, cameraModel) {
312
+ let msg = {
313
+ d: data,
314
+ p: this._impl,
315
+ width, height, token, userFacing,
316
+ c2d: cameraToDevice,
317
+ cm: cameraModel,
318
+ t: "cameraFrameC2S"
319
+ };
320
+ this._mgr.postOutgoingMessage(msg, [data]);
252
321
  }
253
322
  }
254
323
  exports.Pipeline = Pipeline;
package/lib/profile.d.ts CHANGED
@@ -13,4 +13,6 @@ export declare let profile: {
13
13
  dataWidth: number;
14
14
  dataHeight: number;
15
15
  videoElementInDOM: boolean;
16
+ preferMediaStreamTrackProcessorCamera: boolean;
17
+ preferImageBitmapCamera: boolean;
16
18
  };