@zappar/zappar-cv 0.3.13 → 0.4.0-beta.10

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 (61) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +2 -2
  3. package/lib/additional.d.ts +2 -1
  4. package/lib/camera-source-map.d.ts +10 -0
  5. package/lib/camera-source-map.js +40 -0
  6. package/lib/camera-source.d.ts +3 -5
  7. package/lib/camera-source.js +8 -15
  8. package/lib/deserializer.d.ts +1 -0
  9. package/lib/deserializer.js +7 -0
  10. package/lib/drawcamera.js +2 -1
  11. package/lib/gen/zappar-client.d.ts +1 -0
  12. package/lib/gen/zappar-client.js +78 -41
  13. package/lib/gen/zappar-cwrap.js +71 -20
  14. package/lib/gen/zappar-native.d.ts +20 -3
  15. package/lib/gen/zappar-native.js +13 -1
  16. package/lib/gen/zappar-server.d.ts +3 -0
  17. package/lib/gen/zappar-server.js +70 -34
  18. package/lib/gen/zappar.d.ts +29 -1
  19. package/lib/gen/zappar.js +5 -3
  20. package/lib/gfx.d.ts +1 -0
  21. package/lib/gfx.js +4 -0
  22. package/lib/gl-state-manager.d.ts +9 -0
  23. package/lib/gl-state-manager.js +35 -0
  24. package/lib/html-element-source.d.ts +7 -22
  25. package/lib/html-element-source.js +30 -289
  26. package/lib/image-process-gl.d.ts +37 -0
  27. package/lib/image-process-gl.js +298 -0
  28. package/lib/imagebitmap-camera-source.d.ts +36 -0
  29. package/lib/imagebitmap-camera-source.js +277 -0
  30. package/lib/imagetracker.d.ts +28 -0
  31. package/lib/imagetracker.js +119 -0
  32. package/lib/index.d.ts +1 -1
  33. package/lib/mstp-camera-source.d.ts +29 -0
  34. package/lib/mstp-camera-source.js +230 -0
  35. package/lib/native.js +129 -6
  36. package/lib/pipeline.d.ts +22 -2
  37. package/lib/pipeline.js +140 -19
  38. package/lib/profile.d.ts +2 -0
  39. package/lib/profile.js +21 -6
  40. package/lib/riff-reader.d.ts +18 -0
  41. package/lib/riff-reader.js +56 -0
  42. package/lib/sequencerecorder.d.ts +83 -0
  43. package/lib/sequencerecorder.js +283 -0
  44. package/lib/sequencesource.d.ts +23 -0
  45. package/lib/sequencesource.js +170 -0
  46. package/lib/serializer.d.ts +1 -0
  47. package/lib/serializer.js +1 -0
  48. package/lib/source.d.ts +10 -3
  49. package/lib/version.d.ts +1 -1
  50. package/lib/version.js +1 -1
  51. package/lib/worker-imagebitmap.d.ts +5 -0
  52. package/lib/worker-imagebitmap.js +63 -0
  53. package/lib/worker-server.js +124 -8
  54. package/lib/workerinterface.d.ts +50 -1
  55. package/lib/zcv.js +121 -197
  56. package/lib/zcv.wasm +0 -0
  57. package/package.json +34 -31
  58. package/umd/e9486c1cdadb21608a4f7e2fa3be9517.wasm +0 -0
  59. package/umd/zappar-cv.js +1 -9
  60. package/umd/zappar-cv.worker.js +1 -1
  61. package/umd/0bdbfe863a384bcd2935e7437d8f1153.wasm +0 -0
package/lib/pipeline.js CHANGED
@@ -9,7 +9,10 @@ const drawfaceproject_1 = require("./drawfaceproject");
9
9
  const drawplane_1 = require("./drawplane");
10
10
  const event_1 = require("./event");
11
11
  const loglevel_1 = require("./loglevel");
12
+ const sequencerecorder_1 = require("./sequencerecorder");
13
+ const camera_source_map_1 = require("./camera-source-map");
12
14
  let byId = new Map();
15
+ let identity = gl_matrix_1.mat4.create();
13
16
  class Pipeline {
14
17
  constructor(_client, _impl, _mgr) {
15
18
  this._client = _client;
@@ -21,6 +24,8 @@ class Pipeline {
21
24
  this.tokensInFlight = 0;
22
25
  this.videoTextures = [];
23
26
  this.cameraPixelArrays = [];
27
+ this._sequenceRecordDeviceAttitudeMatrices = true;
28
+ this._sequenceRecorderFirstCameraToken = 0;
24
29
  this.onGLContextReset = new event_1.Event();
25
30
  }
26
31
  static create(client, mgr) {
@@ -41,6 +46,10 @@ class Pipeline {
41
46
  }, [msg]);
42
47
  }
43
48
  this.pendingMessages = [];
49
+ this.cleanOldFrames();
50
+ }
51
+ cleanOldFrames() {
52
+ var _a, _b;
44
53
  let currentToken = this._client.pipeline_camera_frame_user_data(this._impl);
45
54
  if (!currentToken)
46
55
  return;
@@ -48,14 +57,45 @@ class Pipeline {
48
57
  if (t[0] < currentToken) {
49
58
  if (t[1].texture)
50
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);
51
61
  this.cameraTokens.delete(t[0]);
52
62
  }
53
63
  }
54
64
  }
55
- cameraTokenReturn(tokenId, pixelArray) {
56
- this.cameraPixelArrays.push(pixelArray);
65
+ cameraTokenReturn(msg) {
66
+ if (this._sequenceRecorder && this._sequenceRecordDeviceAttitudeMatrices
67
+ && msg.token >= this._sequenceRecorderFirstCameraToken) {
68
+ let info = this.cameraTokens.get(msg.token);
69
+ if (info) {
70
+ if (msg.att)
71
+ this._sequenceRecorder.appendAttitudeMatrix(msg.att);
72
+ info.data = msg.d;
73
+ this._sequenceRecorder.appendCameraFrame(info);
74
+ }
75
+ }
76
+ this.cameraPixelArrays.push(msg.d);
57
77
  this.tokensInFlight--;
58
78
  }
79
+ sequenceRecordStart(expectedFrames) {
80
+ if (!this._sequenceRecorder)
81
+ this._sequenceRecorder = new sequencerecorder_1.SequenceRecorder(expectedFrames);
82
+ this._sequenceRecorder.start();
83
+ this._sequenceRecorderFirstCameraToken = this.nextCameraToken;
84
+ }
85
+ sequenceRecordStop() {
86
+ var _a;
87
+ (_a = this._sequenceRecorder) === null || _a === void 0 ? void 0 : _a.stop();
88
+ }
89
+ sequenceRecordData() {
90
+ var _a;
91
+ return ((_a = this._sequenceRecorder) === null || _a === void 0 ? void 0 : _a.data()) || new Uint8Array(0);
92
+ }
93
+ sequenceRecordClear() {
94
+ delete this._sequenceRecorder;
95
+ }
96
+ sequenceRecordDeviceAttitudeMatrices(v) {
97
+ this._sequenceRecordDeviceAttitudeMatrices = v;
98
+ }
59
99
  getVideoTexture() {
60
100
  return this.videoTextures.pop();
61
101
  }
@@ -144,7 +184,7 @@ class Pipeline {
144
184
  let info = this.getCurrentCameraInfo();
145
185
  if (!info)
146
186
  return gl_matrix_1.mat4.create();
147
- 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);
148
188
  }
149
189
  cameraFrameUserFacing() {
150
190
  var _a;
@@ -161,6 +201,47 @@ class Pipeline {
161
201
  gl_matrix_1.mat4.invert(res, res);
162
202
  return res;
163
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
+ }
164
245
  processGL() {
165
246
  if (!this.glContext) {
166
247
  loglevel_1.zcerr("no GL context for camera frames - please call pipeline_gl_context_set");
@@ -172,32 +253,72 @@ class Pipeline {
172
253
  this.currentCameraSource.getFrame(true);
173
254
  return;
174
255
  }
175
- let info = this.currentCameraSource.getFrame(false);
176
- if (!info)
177
- return;
178
- let tokenId = this.nextCameraToken++;
179
- this.cameraTokens.set(tokenId, info);
180
- let msg = {
181
- d: info.data,
182
- p: this._impl,
183
- width: info.dataWidth,
184
- height: info.dataHeight,
185
- token: tokenId,
186
- userFacing: info.userFacing,
187
- t: "cameraFrameC2S"
188
- };
189
- this.tokensInFlight++;
190
- this._mgr.postOutgoingMessage(msg, [info.data]);
256
+ this.currentCameraSource.getFrame(false);
191
257
  }
192
258
  motionAccelerometerSubmit(timestamp, x, y, z) {
259
+ var _a;
260
+ if (!this._sequenceRecordDeviceAttitudeMatrices)
261
+ (_a = this._sequenceRecorder) === null || _a === void 0 ? void 0 : _a.appendAccelerometer(timestamp, x, y, z);
193
262
  this._client.pipeline_motion_accelerometer_submit(this._impl, timestamp, x, y, z);
194
263
  }
195
264
  motionRotationRateSubmit(timestamp, x, y, z) {
265
+ var _a;
266
+ if (!this._sequenceRecordDeviceAttitudeMatrices)
267
+ (_a = this._sequenceRecorder) === null || _a === void 0 ? void 0 : _a.appendRotationRate(timestamp, x, y, z);
196
268
  this._client.pipeline_motion_rotation_rate_submit(this._impl, timestamp, x, y, z);
197
269
  }
198
270
  motionAttitudeSubmit(timestamp, x, y, z) {
271
+ var _a;
272
+ if (!this._sequenceRecordDeviceAttitudeMatrices)
273
+ (_a = this._sequenceRecorder) === null || _a === void 0 ? void 0 : _a.appendAttitude(timestamp, x, y, z);
199
274
  this._client.pipeline_motion_attitude_submit(this._impl, timestamp, x, y, z);
200
275
  }
276
+ motionAttitudeMatrix(m) {
277
+ // This doesn't need to be added to the sequence since that's done on frame update instead
278
+ this._client.pipeline_motion_attitude_matrix_submit(this._impl, m);
279
+ }
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]);
321
+ }
201
322
  }
202
323
  exports.Pipeline = Pipeline;
203
324
  function applyScreenCounterRotation(info, inp) {
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
  };
package/lib/profile.js CHANGED
@@ -17,15 +17,27 @@ 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["zeeProfile"] = exports.profile;
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
36
  let os = (agent.getOS().name || "unknown").toLowerCase();
25
37
  let engine = (agent.getEngine().name || "unknown").toLowerCase();
26
38
  if (engine === "webkit" && os !== "ios") {
27
39
  exports.profile.deviceMotionMutliplier = 1.0;
28
- if (window.orientation !== undefined) {
40
+ if (typeof window !== "undefined" && window.orientation !== undefined) {
29
41
  // iPad
30
42
  iDevice();
31
43
  }
@@ -59,9 +71,12 @@ function iDevice() {
59
71
  navigator.mediaDevices.getSupportedConstraints &&
60
72
  navigator.mediaDevices.getSupportedConstraints().frameRate) {
61
73
  exports.profile.requestHighFrameRate = true;
62
- // Avoid bug where iOS letterboxes 16:9 into 4:3 for high fps
63
- exports.profile.videoHeight = 360;
64
- exports.profile.dataHeight = 180;
74
+ if (majorVersion < 14) {
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
77
+ exports.profile.videoHeight = 360;
78
+ exports.profile.dataHeight = 180;
79
+ }
65
80
  }
66
81
  }
67
82
  }
@@ -0,0 +1,18 @@
1
+ export interface Chunk {
2
+ ident: string;
3
+ data: Uint8Array;
4
+ subident?: string;
5
+ subchunks?: Chunk[];
6
+ }
7
+ export declare class RiffReader {
8
+ private _data;
9
+ private _paddingBytes;
10
+ truncatedChunks: boolean;
11
+ private _view;
12
+ root: Chunk;
13
+ constructor(_data: ArrayBuffer, _paddingBytes?: boolean);
14
+ private _parse;
15
+ private _parseChunk;
16
+ find(str: string, inChunk?: Chunk): Chunk | undefined;
17
+ has(str: string): boolean;
18
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RiffReader = void 0;
4
+ const decoder = new TextDecoder();
5
+ class RiffReader {
6
+ constructor(_data, _paddingBytes = false) {
7
+ this._data = _data;
8
+ this._paddingBytes = _paddingBytes;
9
+ this.truncatedChunks = false;
10
+ this._view = new DataView(this._data);
11
+ this.root = this._parse();
12
+ }
13
+ _parse() {
14
+ const header = decoder.decode(this._data.slice(0, 4));
15
+ if (header !== "RIFF")
16
+ throw new Error("Not a valid ZPT file");
17
+ return this._parseChunk(0);
18
+ }
19
+ _parseChunk(offset) {
20
+ const ident = decoder.decode(this._data.slice(offset, offset + 4));
21
+ const length = this._view.getUint32(offset + 4, true);
22
+ const data = new Uint8Array(this._data, offset + 8, length);
23
+ if (data.byteLength !== length)
24
+ this.truncatedChunks = true;
25
+ let subchunks;
26
+ let subident;
27
+ if (ident === "RIFF" || ident === "LIST") {
28
+ subident = decoder.decode(this._data.slice(offset + 8, offset + 12));
29
+ subchunks = [];
30
+ let currentOffset = 4;
31
+ while (currentOffset < data.byteLength - 1) {
32
+ const subchunk = this._parseChunk(offset + 8 + currentOffset);
33
+ subchunks.push(subchunk);
34
+ currentOffset += subchunk.data.byteLength + 8;
35
+ if (this._paddingBytes && subchunk.data.byteLength & 0x1)
36
+ currentOffset++;
37
+ }
38
+ }
39
+ return { ident, data, subident, subchunks };
40
+ }
41
+ find(str, inChunk = this.root) {
42
+ if (inChunk.ident === str)
43
+ return inChunk;
44
+ if (!inChunk.subchunks)
45
+ return;
46
+ for (let c of inChunk.subchunks) {
47
+ const found = this.find(str, c);
48
+ if (found)
49
+ return found;
50
+ }
51
+ }
52
+ has(str) {
53
+ return this.find(str) !== undefined;
54
+ }
55
+ }
56
+ exports.RiffReader = RiffReader;
@@ -0,0 +1,83 @@
1
+ import { CameraFrameInfo } from "./source";
2
+ export declare enum SequenceRecorderPacketType {
3
+ CAMERA_FRAME = 0,
4
+ ACCELEROMETER = 1,
5
+ ROTATION_RATE = 2,
6
+ ATTITUDE = 3,
7
+ ATTITUDE_MATRIX = 4
8
+ }
9
+ export declare class SequenceRecorder {
10
+ static headerSizeBytes: number;
11
+ static psbPacketType: number;
12
+ static psbCameraFrameWidth: number;
13
+ static psbCameraFrameHeight: number;
14
+ static psbFlags: number;
15
+ static psbCameraToDeviceTransform: number;
16
+ static psbCameraModel: number;
17
+ static cameraPacketSizeBytes: number;
18
+ static accelerometerPacketSizeBytes: number;
19
+ static rotationRatePacketSizeBytes: number;
20
+ static attitudePacketSizeBytes: number;
21
+ static attitudeMatrixPacketSizeBytes: number;
22
+ private _data;
23
+ private _dataView;
24
+ private _dataUint8;
25
+ private _dataFloat32;
26
+ private _insertionByte;
27
+ private _numberPackets;
28
+ private _started;
29
+ private _hasLoggedUnsuppored;
30
+ constructor(estimatedFrames: number);
31
+ private _estimatedSize;
32
+ start(): void;
33
+ stop(): void;
34
+ data(): Uint8Array;
35
+ appendCameraFrame(c: CameraFrameInfo): void;
36
+ appendAccelerometer(t: number, x: number, y: number, z: number): void;
37
+ appendRotationRate(t: number, x: number, y: number, z: number): void;
38
+ appendAttitude(t: number, x: number, y: number, z: number): void;
39
+ private _appendTimestampedVec3;
40
+ appendAttitudeMatrix(m: Float32Array): void;
41
+ private _growArrayBuffer;
42
+ }
43
+ export interface SequenceCameraData {
44
+ type: SequenceRecorderPacketType.CAMERA_FRAME;
45
+ width: number;
46
+ height: number;
47
+ greyscale: Uint8Array;
48
+ userFacing: boolean;
49
+ cameraToDevice: Float32Array;
50
+ cameraModel: Float32Array;
51
+ }
52
+ export interface SequenceVec3Data {
53
+ t: number;
54
+ x: number;
55
+ y: number;
56
+ z: number;
57
+ }
58
+ export interface SequenceAccelerometerData extends SequenceVec3Data {
59
+ type: SequenceRecorderPacketType.ACCELEROMETER;
60
+ }
61
+ export interface SequenceRotationRateData extends SequenceVec3Data {
62
+ type: SequenceRecorderPacketType.ROTATION_RATE;
63
+ }
64
+ export interface SequenceAttitudeData extends SequenceVec3Data {
65
+ type: SequenceRecorderPacketType.ATTITUDE;
66
+ }
67
+ export interface SequenceAttitudeMatrixData {
68
+ type: SequenceRecorderPacketType.ATTITUDE_MATRIX;
69
+ attitude: Float32Array;
70
+ }
71
+ export declare type SequencePacketData = SequenceCameraData | SequenceAccelerometerData | SequenceRotationRateData | SequenceAttitudeData | SequenceAttitudeMatrixData;
72
+ export declare class SequenceDecoder {
73
+ private _data;
74
+ dataByPacket: Map<number, SequencePacketData>;
75
+ dataByCameraFrame: Map<number, SequenceCameraData>;
76
+ numberPackets: number;
77
+ numberCameraFrames: number;
78
+ numberAccelerometerPackets: number;
79
+ numberRotationRatePackets: number;
80
+ numberAttitudePackets: number;
81
+ numberAttitudeMatrixPackets: number;
82
+ constructor(_data: ArrayBuffer);
83
+ }