@luxonis/visualizer-protobuf 3.1.11 → 3.1.12

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 (81) hide show
  1. package/dist/{FoxgloveServer-B98MHUu6.js → FoxgloveServer-Da9kV1cr.js} +1 -1
  2. package/dist/{communicator-Bzkx3Qfr.js → communicator-Dh2aL-rj.js} +1 -1
  3. package/dist/{depth-DlC6A3Te.js → depth-DiD1V2Sg.js} +15 -28
  4. package/dist/{deserialization.worker-CO4m6y8V.js → deserialization.worker-CxHfbNSI.js} +544 -325
  5. package/dist/{foxglove-protocol-yHdoBNaD.js → foxglove-protocol-BtLMVx24.js} +1 -1
  6. package/dist/{index-D063HnO-.js → index-8bTMarZg.js} +5 -5
  7. package/dist/{index-BXzWxQD4.js → index-9Qz76jnn.js} +7 -7
  8. package/dist/{index-Dqm1x8G2.js → index-B5oN0fQm.js} +1 -1
  9. package/dist/{index-CKE7xLWy.js → index-B8JZ9tAh.js} +5 -5
  10. package/dist/{index-CB1fYMKI.js → index-BFAcwVLJ.js} +5 -5
  11. package/dist/{index-DCsDqt-U.js → index-BtMMMbp8.js} +5 -5
  12. package/dist/{index-BYTk-1GW.js → index-BvC_JYBX.js} +5 -5
  13. package/dist/{index-BlROWu-J.js → index-BydKxany.js} +6 -6
  14. package/dist/{index-DtnnnQqJ.js → index-C-n27_wk.js} +5 -5
  15. package/dist/{index-DXmbPIsN.js → index-CQhsew4_.js} +5 -5
  16. package/dist/{index-Dvd5sByT.js → index-CVrY6MoS.js} +5 -5
  17. package/dist/{index-CDp9Pzg1.js → index-CwAmHvi3.js} +5 -5
  18. package/dist/{index-D_pNGJGQ.js → index-DXdd6C_Q.js} +5 -5
  19. package/dist/{index-DgUF0rJi.js → index-D_TjqfY9.js} +5 -5
  20. package/dist/{index-DCsBkCC7.js → index-DnaaNoIT.js} +5 -5
  21. package/dist/{index-D0BOBLGo.js → index-DuP_Wg3E.js} +5 -5
  22. package/dist/{index-B-g3aWAt.js → index-O1aT66OM.js} +5 -5
  23. package/dist/{index-BEUjTghZ.js → index-RxEWv1Fn.js} +5 -5
  24. package/dist/{index-Be6EYnox.js → index-gafqmUmi.js} +49 -35
  25. package/dist/{index-OIOsl1pr.js → index-oyn_LQK1.js} +5 -5
  26. package/dist/{index-D2sxEb00.js → index-yO9F9DL5.js} +5 -5
  27. package/dist/index.js +5 -5
  28. package/dist/lib/src/connection/foxglove-connection.d.ts.map +1 -1
  29. package/dist/lib/src/connection/foxglove-connection.js +7 -1
  30. package/dist/lib/src/connection/foxglove-connection.js.map +1 -1
  31. package/dist/lib/src/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js +2 -2
  32. package/dist/lib/src/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js.map +1 -1
  33. package/dist/lib/src/messaging/deserialization/pointcloud/poitcloudPoolManager.js.map +1 -1
  34. package/dist/lib/src/messaging/deserialization/pointcloud/utils.d.ts.map +1 -1
  35. package/dist/lib/src/messaging/deserialization/pointcloud/utils.js.map +1 -1
  36. package/dist/lib/src/messaging/deserialization/video/depth.d.ts.map +1 -1
  37. package/dist/lib/src/messaging/deserialization/video/depth.js +11 -1
  38. package/dist/lib/src/messaging/deserialization/video/depth.js.map +1 -1
  39. package/dist/lib/src/messaging/deserialization/video/h264.d.ts +9 -6
  40. package/dist/lib/src/messaging/deserialization/video/h264.d.ts.map +1 -1
  41. package/dist/lib/src/messaging/deserialization/video/h264.js +104 -163
  42. package/dist/lib/src/messaging/deserialization/video/h264.js.map +1 -1
  43. package/dist/lib/src/messaging/deserialization/video/h265.d.ts +0 -7
  44. package/dist/lib/src/messaging/deserialization/video/h265.d.ts.map +1 -1
  45. package/dist/lib/src/messaging/deserialization/video/h265.js +46 -123
  46. package/dist/lib/src/messaging/deserialization/video/h265.js.map +1 -1
  47. package/dist/lib/src/messaging/deserialization/video/mjpeg.d.ts.map +1 -1
  48. package/dist/lib/src/messaging/deserialization/video/mjpeg.js +7 -8
  49. package/dist/lib/src/messaging/deserialization/video/mjpeg.js.map +1 -1
  50. package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.d.ts +17 -0
  51. package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.d.ts.map +1 -0
  52. package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.js +320 -0
  53. package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.js.map +1 -0
  54. package/dist/lib/src/messaging/deserialization.worker.d.ts +4 -0
  55. package/dist/lib/src/messaging/deserialization.worker.d.ts.map +1 -1
  56. package/dist/lib/src/messaging/deserialization.worker.js +16 -3
  57. package/dist/lib/src/messaging/deserialization.worker.js.map +1 -1
  58. package/dist/lib/src/messaging/protobuf.d.ts +12 -1
  59. package/dist/lib/src/messaging/protobuf.d.ts.map +1 -1
  60. package/dist/lib/src/messaging/protobuf.js +8 -0
  61. package/dist/lib/src/messaging/protobuf.js.map +1 -1
  62. package/dist/lib/src/messaging/utils.d.ts.map +1 -1
  63. package/dist/lib/src/messaging/utils.js +2 -0
  64. package/dist/lib/src/messaging/utils.js.map +1 -1
  65. package/dist/lib/src/output.css +2 -21
  66. package/dist/lib/src/panels/PointCloudPanel.d.ts.map +1 -1
  67. package/dist/lib/src/panels/PointCloudPanel.js +5 -1
  68. package/dist/lib/src/panels/PointCloudPanel.js.map +1 -1
  69. package/dist/lib/src/utils/metrics-manager.d.ts +1 -0
  70. package/dist/lib/src/utils/metrics-manager.d.ts.map +1 -1
  71. package/dist/lib/src/utils/metrics-manager.js +4 -2
  72. package/dist/lib/src/utils/metrics-manager.js.map +1 -1
  73. package/dist/lib/src/utils/poitcloud-sync.d.ts +4 -3
  74. package/dist/lib/src/utils/poitcloud-sync.d.ts.map +1 -1
  75. package/dist/lib/src/utils/poitcloud-sync.js +3 -1
  76. package/dist/lib/src/utils/poitcloud-sync.js.map +1 -1
  77. package/dist/{pointcloudFromDepth.worker-JLptpLHr.js → pointcloudFromDepth.worker-60RA4Ief.js} +2 -2
  78. package/dist/{protobuf-Be0G3NFz.js → protobuf-OcbVtxg1.js} +406 -218
  79. package/dist/{worker-NFznpx6V.js → worker-Be-hru8f.js} +3 -3
  80. package/dist/{worker-0Q6os6Ck.js → worker-C2MHIq3t.js} +4 -4
  81. package/package.json +2 -2
@@ -6,19 +6,9 @@ import { estimateObjectSize } from "@foxglove/studio-base/players/messageMemoryE
6
6
  import { ensureWebCodecsSupported } from "../../../utils/compatibility.js";
7
7
  import { DecoderRuntimeError } from "../../../utils/error.js";
8
8
  import { Logger } from "../../../utils/logger";
9
- import { parseMessage, parsePixelFormat } from "../../utils.js";
9
+ import { parseMessage } from "../../utils.js";
10
+ import { copyVideoFrameToI420 } from "./h264.js";
10
11
  const logger = Logger.getLogger();
11
- function configureDecoder(decoder) {
12
- decoder.configure({
13
- codec: "hev1.1.6.L93.B0",
14
- optimizeForLatency: true,
15
- });
16
- }
17
- function ensureDecoderConfigured(decoder) {
18
- if (decoder.state === "unconfigured") {
19
- configureDecoder(decoder);
20
- }
21
- }
22
12
  function closeDecoder(decoder) {
23
13
  if (!decoder) {
24
14
  return;
@@ -35,114 +25,27 @@ function closeDecoder(decoder) {
35
25
  }
36
26
  function closeTopicDecoder(topic, topicDecoders) {
37
27
  const decoderInfo = topicDecoders.get(topic);
38
- topicDecoders.delete(topic);
39
28
  closeDecoder(decoderInfo?.decoder);
40
29
  decoderInfo?.timing.clear();
41
30
  decoderInfo?.transformations.clear();
42
- if (decoderInfo) {
43
- decoderInfo.pendingFrame = undefined;
44
- }
45
- }
46
- function isUnconfiguredCodecError(error) {
47
- const message = error instanceof Error ? error.message : String(error);
48
- return /cannot call ["']decode["'] on an unconfigured (?:codec|decoder)/i.test(message);
49
- }
50
- function resetTopicDecoder({ topic, topicDecoders, callback, onError, }) {
51
- const existingDecoderInfo = topicDecoders.get(topic);
52
- closeDecoder(existingDecoderInfo?.decoder);
53
- const decoder = createVideoDecoder({ topic, callback, topicDecoders, onError });
54
- try {
55
- configureDecoder(decoder);
56
- }
57
- catch (error) {
58
- closeDecoder(decoder);
59
- closeTopicDecoder(topic, topicDecoders);
60
- onError(new DecoderRuntimeError(topic, error instanceof Error ? error.message : "Failed to configure H.265 decoder."));
61
- return undefined;
62
- }
63
- if (existingDecoderInfo) {
64
- existingDecoderInfo.decoder = decoder;
65
- existingDecoderInfo.timing.clear();
66
- existingDecoderInfo.transformations.clear();
67
- existingDecoderInfo.pendingFrame = undefined;
68
- }
69
- else {
70
- topicDecoders.set(topic, {
71
- decoder,
72
- timing: new Map(),
73
- transformations: new Map(),
74
- pendingFrame: undefined,
75
- });
76
- }
77
- return decoder;
78
- }
79
- function decodePendingFrame(topic, topicDecoders, callback, onError) {
80
- const decoderInfo = topicDecoders.get(topic);
81
- if (!decoderInfo) {
82
- return;
83
- }
84
- const decoder = decoderInfo.decoder;
85
- if (decoder.state === "closed" || decoder.decodeQueueSize > 0) {
86
- return;
87
- }
88
- const pendingFrame = decoderInfo.pendingFrame;
89
- if (!pendingFrame) {
90
- return;
91
- }
92
- decoderInfo.pendingFrame = undefined;
93
- decoderInfo.timing.set(pendingFrame.timestamp, pendingFrame.receiveTime);
94
- decoderInfo.transformations.set(pendingFrame.timestamp, pendingFrame.transformation);
95
- try {
96
- ensureDecoderConfigured(decoder);
97
- if (decoder.state !== "configured" || topicDecoders.get(topic)?.decoder !== decoder) {
98
- closeTopicDecoder(topic, topicDecoders);
99
- return;
100
- }
101
- const chunk = new EncodedVideoChunk({
102
- type: "key",
103
- data: pendingFrame.data,
104
- timestamp: pendingFrame.timestamp,
105
- });
106
- decoder.decode(chunk);
107
- }
108
- catch (error) {
109
- if (isUnconfiguredCodecError(error)) {
110
- decoderInfo.pendingFrame = pendingFrame;
111
- const replacementDecoder = resetTopicDecoder({ topic, topicDecoders, callback, onError });
112
- if (replacementDecoder?.state === "configured") {
113
- decodePendingFrame(topic, topicDecoders, callback, onError);
114
- }
115
- return;
116
- }
117
- closeTopicDecoder(topic, topicDecoders);
118
- onError(new DecoderRuntimeError(topic, error instanceof Error ? error.message : "Failed to decode H.265 frame."));
119
- }
120
31
  }
121
32
  function createVideoDecoder({ topic, callback, topicDecoders, onError, }) {
122
- let decoder;
123
- decoder = new VideoDecoder({
33
+ return new VideoDecoder({
124
34
  output: async (frame) => {
125
- if (topicDecoders.get(topic)?.decoder !== decoder) {
126
- frame.close();
127
- return;
128
- }
129
- const buffer = new Uint8Array(frame.allocationSize());
130
- await frame.copyTo(buffer);
35
+ const { data: buffer, width, height } = await copyVideoFrameToI420(frame, "H265");
131
36
  const receiveTime = topicDecoders.get(topic)?.timing.get(frame.timestamp)
132
37
  ??
133
38
  fromMicros(frame.timestamp);
134
- topicDecoders.get(topic)?.timing.delete(frame.timestamp);
135
39
  const transformation = topicDecoders.get(topic)?.transformations.get(frame.timestamp);
136
40
  topicDecoders.get(topic)?.transformations.delete(frame.timestamp);
137
- const [encoding, step] = parsePixelFormat(frame.format);
138
41
  const foxgloveMessage = {
139
42
  timestamp: receiveTime,
140
43
  frame_id: `h265-${topic}-frame`,
141
- width: frame.displayWidth,
142
- height: frame.displayHeight,
44
+ width,
45
+ height,
143
46
  data: buffer,
144
- encoding,
145
- step: frame.displayWidth * step
47
+ encoding: "yuv420p",
48
+ step: width,
146
49
  };
147
50
  callback({
148
51
  topic,
@@ -153,20 +56,13 @@ function createVideoDecoder({ topic, callback, topicDecoders, onError, }) {
153
56
  depthaiTransformation: transformation,
154
57
  });
155
58
  frame.close();
156
- if (topicDecoders.get(topic)?.decoder === decoder) {
157
- decodePendingFrame(topic, topicDecoders, callback, onError);
158
- }
159
59
  },
160
60
  error: (error) => {
161
- if (topicDecoders.get(topic)?.decoder !== decoder) {
162
- return;
163
- }
164
61
  logger.error(error);
165
62
  closeTopicDecoder(topic, topicDecoders);
166
63
  onError(new DecoderRuntimeError(topic, error.message));
167
64
  },
168
65
  });
169
- return decoder;
170
66
  }
171
67
  export async function deserializeEncodedFrameH265({ topic, message, topicDecoders, callback, onError, }) {
172
68
  const { receiveTime } = parseMessage(message);
@@ -175,28 +71,55 @@ export async function deserializeEncodedFrameH265({ topic, message, topicDecoder
175
71
  return;
176
72
  }
177
73
  const existingDecoderInfo = topicDecoders.get(topic);
178
- if (!existingDecoderInfo || existingDecoderInfo.decoder.state !== "configured") {
179
- const decoder = resetTopicDecoder({ topic, callback, topicDecoders, onError });
180
- if (!decoder) {
74
+ if (!existingDecoderInfo || existingDecoderInfo.decoder.state === "closed") {
75
+ const decoder = createVideoDecoder({ topic, callback, topicDecoders, onError });
76
+ try {
77
+ decoder.configure({
78
+ codec: "hev1.1.6.L93.B0",
79
+ optimizeForLatency: true
80
+ });
81
+ }
82
+ catch (error) {
83
+ closeDecoder(decoder);
84
+ onError(new DecoderRuntimeError(topic, error instanceof Error ? error.message : "Failed to configure H.265 decoder."));
181
85
  return;
182
86
  }
87
+ if (existingDecoderInfo) {
88
+ existingDecoderInfo.decoder = decoder;
89
+ existingDecoderInfo.timing.clear();
90
+ existingDecoderInfo.transformations.clear();
91
+ }
92
+ else {
93
+ topicDecoders.set(topic, {
94
+ decoder,
95
+ timing: new Map(),
96
+ transformations: new Map(),
97
+ });
98
+ }
183
99
  }
184
100
  const decoderInfo = topicDecoders.get(topic);
185
101
  if (!decoderInfo) {
186
102
  return;
187
103
  }
104
+ if (decoderInfo.decoder.decodeQueueSize > 60) {
105
+ decoderInfo.decoder.reset();
106
+ return;
107
+ }
188
108
  const microTimestamp = receiveTime.sec * 1_000_000 + Math.floor(receiveTime.nsec / 1_000);
109
+ decoderInfo.timing.set(microTimestamp, receiveTime);
110
+ decoderInfo.transformations.set(microTimestamp, message.transformation);
189
111
  const frame = {
112
+ type: 'key',
190
113
  data: message.data,
191
- timestamp: microTimestamp,
192
- receiveTime,
193
- transformation: message.transformation,
114
+ timestamp: microTimestamp
194
115
  };
195
- if (decoderInfo.decoder.decodeQueueSize > 0) {
196
- decoderInfo.pendingFrame = frame;
197
- return;
116
+ try {
117
+ const chunk = new EncodedVideoChunk(frame);
118
+ decoderInfo.decoder.decode(chunk);
119
+ }
120
+ catch (error) {
121
+ closeTopicDecoder(topic, topicDecoders);
122
+ onError(new DecoderRuntimeError(topic, error instanceof Error ? error.message : "Failed to decode H.265 frame."));
198
123
  }
199
- decoderInfo.pendingFrame = frame;
200
- decodePendingFrame(topic, topicDecoders, callback, onError);
201
124
  }
202
125
  //# sourceMappingURL=h265.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"h265.js","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/h265.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"h265.js","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/h265.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mjpeg.d.ts","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/mjpeg.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,6CAA6C,CAAC;AAI3E,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF,wBAAsB,qBAAqB,CAAC,EAC1C,KAAK,EACL,OAAO,EACP,QAAQ,EACT,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC3C"}
1
+ {"version":3,"file":"mjpeg.d.ts","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/mjpeg.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,6CAA6C,CAAC;AAK3E,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF,wBAAsB,qBAAqB,CAAC,EAC1C,KAAK,EACL,OAAO,EACP,QAAQ,EACT,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC3C"}
@@ -3,7 +3,8 @@
3
3
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
4
4
  import { estimateObjectSize } from "@foxglove/studio-base/players/messageMemoryEstimation.js";
5
5
  import { ensureWebCodecsSupported } from "../../../utils/compatibility.js";
6
- import { parseMessage, parsePixelFormat } from "../../utils.js";
6
+ import { parseMessage } from "../../utils.js";
7
+ import { copyVideoFrameToI420 } from "./h264.js";
7
8
  export async function deserializeMJPEGFrame({ topic, message, callback }) {
8
9
  const { receiveTime } = parseMessage(message);
9
10
  const supported = ensureWebCodecsSupported("ImageDecoder");
@@ -15,17 +16,15 @@ export async function deserializeMJPEGFrame({ topic, message, callback }) {
15
16
  data: message.data
16
17
  });
17
18
  const { image: frame } = await decoder.decode();
18
- const buffer = new Uint8Array(frame.allocationSize());
19
- await frame.copyTo(buffer);
20
- const [encoding, step] = parsePixelFormat(frame.format);
19
+ const { data: buffer, width, height } = await copyVideoFrameToI420(frame, "MJPEG");
21
20
  const foxgloveMessage = {
22
21
  timestamp: receiveTime,
23
22
  frame_id: "camera",
24
- width: frame.displayWidth,
25
- height: frame.displayHeight,
23
+ width,
24
+ height,
26
25
  data: buffer,
27
- encoding,
28
- step: frame.displayWidth * step
26
+ encoding: "yuv420p",
27
+ step: width,
29
28
  };
30
29
  frame.close();
31
30
  callback({
@@ -1 +1 @@
1
- {"version":3,"file":"mjpeg.js","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/mjpeg.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,oEAAoE;AACpE,0DAA0D;AAG1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0DAA0D,CAAC;AAI9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAQhE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,KAAK,EACL,OAAO,EACP,QAAQ,EACkB;IAC1B,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAE7C,MAAM,SAAS,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;QAC/B,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC,CAAC;IAEH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;IACtD,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAE3B,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAExD,MAAM,eAAe,GAAa;QAChC,SAAS,EAAE,WAAW;QACtB,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,KAAK,CAAC,YAAY;QACzB,MAAM,EAAE,KAAK,CAAC,aAAa;QAC3B,IAAI,EAAE,MAAM;QACZ,QAAQ;QACR,IAAI,EAAE,KAAK,CAAC,YAAY,GAAG,IAAI;KAChC,CAAC;IAEF,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,QAAQ,CAAC;QACP,KAAK;QACL,WAAW;QACX,OAAO,EAAE,eAAe;QACxB,WAAW,EAAE,kBAAkB,CAAC,eAAe,CAAC;QAChD,UAAU,EAAE,mBAAmB;QAC/B,qBAAqB,EAAE,OAAO,CAAC,cAAc;KAC9B,CAAC,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"mjpeg.js","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/mjpeg.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,oEAAoE;AACpE,0DAA0D;AAG1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0DAA0D,CAAC;AAI9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAQjD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,KAAK,EACL,OAAO,EACP,QAAQ,EACkB;IAC1B,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAE7C,MAAM,SAAS,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;QAC/B,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC,CAAC;IAEH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAEnF,MAAM,eAAe,GAAa;QAChC,SAAS,EAAE,WAAW;QACtB,QAAQ,EAAE,QAAQ;QAClB,KAAK;QACL,MAAM;QACN,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS;QACnB,IAAI,EAAE,KAAK;KACZ,CAAC;IAEF,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,QAAQ,CAAC;QACP,KAAK;QACL,WAAW;QACX,OAAO,EAAE,eAAe;QACxB,WAAW,EAAE,kBAAkB,CAAC,eAAe,CAAC;QAChD,UAAU,EAAE,mBAAmB;QAC/B,qBAAqB,EAAE,OAAO,CAAC,cAAc;KAC9B,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { MessageEvent } from "@foxglove/studio-base/players/types";
2
+ import { type PointCloudWithDimensions } from "./depth";
3
+ import { type TopicDecoders } from "./h264";
4
+ import type { RGBDData } from "../../../protobuf.generated/RGBDData";
5
+ import type { NeuralCameraIntrinsics } from "../pointcloud/utils";
6
+ export type DeserializeRGBDFrameArgs = {
7
+ topic: string;
8
+ topicDecoders: TopicDecoders;
9
+ cameraIntrinsics: NeuralCameraIntrinsics;
10
+ maxStereoDepth: number;
11
+ message: RGBDData;
12
+ callback: (event: MessageEvent) => void;
13
+ onError: (error: Error) => void;
14
+ };
15
+ export type PointCloudWithColorAndDepth = PointCloudWithDimensions;
16
+ export declare function deserializeRGBDFrameToPointCloud({ topic, topicDecoders, cameraIntrinsics, maxStereoDepth, message, callback, }: DeserializeRGBDFrameArgs): Promise<void>;
17
+ //# sourceMappingURL=rgbd-to-pointcloud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rgbd-to-pointcloud.d.ts","sourceRoot":"","sources":["../../../../../../src/messaging/deserialization/video/rgbd-to-pointcloud.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAExE,OAAO,EAAyB,KAAK,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAkD,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAK5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAIrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAGlE,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,QAAQ,CAAC;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,CAAC;AAqVnE,wBAAsB,gCAAgC,CAAC,EACrD,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,QAAQ,GACT,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E1C"}
@@ -0,0 +1,320 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/
4
+ import { wrap } from "comlink";
5
+ import { NumericType } from "@foxglove/schemas";
6
+ import { estimateObjectSize } from "@foxglove/studio-base/players/messageMemoryEstimation";
7
+ import { deserializeDepthFrame } from "./depth";
8
+ import { convertNv12ToI420, deserializeEncodedFrameH264 } from "./h264";
9
+ import { deserializeEncodedFrameH265 } from "./h265";
10
+ import { deserializeMJPEGFrame } from "./mjpeg";
11
+ import { Profile } from "../../../protobuf.generated/EncodedFrame";
12
+ import { Type } from "../../../protobuf.generated/ImgFrame";
13
+ import { parseMessage } from "../../utils";
14
+ import { Logger } from "../../../utils/logger";
15
+ import { uint8ArrayToUint16Array } from "../pointcloud/utils";
16
+ const RGBD_POINTCLOUD_WORKER_COUNT = 4;
17
+ let cachedRGBDHasGPU;
18
+ let rgbdHasGPUPromise;
19
+ let rgbdPointCloudWorkers;
20
+ let rgbdPointCloudWorkerIndex = 0;
21
+ const logger = Logger.getLogger();
22
+ function ensureEvenByteLength(data) {
23
+ if (data.length % 2 === 0) {
24
+ return data;
25
+ }
26
+ const padded = new Uint8Array(data.length + 1);
27
+ padded.set(data);
28
+ return padded;
29
+ }
30
+ async function detectRGBDGPUSupport() {
31
+ if (cachedRGBDHasGPU != undefined) {
32
+ return cachedRGBDHasGPU;
33
+ }
34
+ if (rgbdHasGPUPromise) {
35
+ return await rgbdHasGPUPromise;
36
+ }
37
+ rgbdHasGPUPromise = (async () => {
38
+ if (typeof navigator.gpu === "undefined") {
39
+ cachedRGBDHasGPU = false;
40
+ return false;
41
+ }
42
+ try {
43
+ const adapter = await navigator.gpu.requestAdapter();
44
+ cachedRGBDHasGPU = adapter != undefined;
45
+ return cachedRGBDHasGPU;
46
+ }
47
+ catch {
48
+ cachedRGBDHasGPU = false;
49
+ return false;
50
+ }
51
+ finally {
52
+ rgbdHasGPUPromise = undefined;
53
+ }
54
+ })();
55
+ return await rgbdHasGPUPromise;
56
+ }
57
+ function getRGBDPointCloudWorkerSlot() {
58
+ if (!rgbdPointCloudWorkers) {
59
+ rgbdPointCloudWorkers = Array.from({ length: RGBD_POINTCLOUD_WORKER_COUNT }, () => {
60
+ const worker = new Worker(new URL("../pointcloud/pointcloudFromDepth.worker", import.meta.url), {
61
+ type: "module",
62
+ });
63
+ return {
64
+ worker,
65
+ remote: wrap(worker),
66
+ activeJobs: 0,
67
+ };
68
+ });
69
+ }
70
+ const slots = rgbdPointCloudWorkers;
71
+ const candidateSlots = slots
72
+ .map((slot, index) => ({ slot, index }))
73
+ .sort((left, right) => {
74
+ if (left.slot.activeJobs !== right.slot.activeJobs) {
75
+ return left.slot.activeJobs - right.slot.activeJobs;
76
+ }
77
+ const leftDistance = (left.index - rgbdPointCloudWorkerIndex + slots.length) % slots.length;
78
+ const rightDistance = (right.index - rgbdPointCloudWorkerIndex + slots.length) % slots.length;
79
+ return leftDistance - rightDistance;
80
+ });
81
+ const selected = candidateSlots[0];
82
+ rgbdPointCloudWorkerIndex = (selected.index + 1) % slots.length;
83
+ return selected.slot;
84
+ }
85
+ function repackYuv420pToI420(imageFrame, width, height) {
86
+ const specs = imageFrame.fb ?? imageFrame.sourceFb;
87
+ const source = ensureEvenByteLength(imageFrame.data);
88
+ const yStride = specs?.stride || width;
89
+ const uvWidth = Math.floor(width / 2);
90
+ const uvHeight = Math.floor(height / 2);
91
+ const uvStride = yStride > width ? Math.floor(yStride / 2) : uvWidth;
92
+ const yPlaneSize = width * height;
93
+ const uvPlaneSize = uvWidth * uvHeight;
94
+ const uOffset = specs?.p1Offset || yStride * height;
95
+ const vOffset = specs?.p2Offset || uOffset + uvStride * uvHeight;
96
+ const i420 = new Uint8Array(yPlaneSize + 2 * uvPlaneSize);
97
+ for (let row = 0; row < height; row++) {
98
+ const srcOffset = row * yStride;
99
+ const dstOffset = row * width;
100
+ i420.set(source.subarray(srcOffset, srcOffset + width), dstOffset);
101
+ }
102
+ for (let row = 0; row < uvHeight; row++) {
103
+ const srcUOffset = uOffset + row * uvStride;
104
+ const srcVOffset = vOffset + row * uvStride;
105
+ const dstOffset = row * uvWidth;
106
+ i420.set(source.subarray(srcUOffset, srcUOffset + uvWidth), yPlaneSize + dstOffset);
107
+ i420.set(source.subarray(srcVOffset, srcVOffset + uvWidth), yPlaneSize + uvPlaneSize + dstOffset);
108
+ }
109
+ return i420;
110
+ }
111
+ function toMatrix3x3(matrix) {
112
+ const rows = matrix?.arrays;
113
+ if (!rows || rows.length < 3) {
114
+ return undefined;
115
+ }
116
+ const normalizedRows = rows
117
+ .slice(0, 3)
118
+ .map((row) => row?.values.slice(0, 3).map((value) => value ?? 0));
119
+ if (normalizedRows.some((row) => !row || row.length < 3)) {
120
+ return undefined;
121
+ }
122
+ return normalizedRows;
123
+ }
124
+ function multiply3x3(left, right) {
125
+ return [
126
+ [
127
+ left[0][0] * right[0][0] + left[0][1] * right[1][0] + left[0][2] * right[2][0],
128
+ left[0][0] * right[0][1] + left[0][1] * right[1][1] + left[0][2] * right[2][1],
129
+ left[0][0] * right[0][2] + left[0][1] * right[1][2] + left[0][2] * right[2][2],
130
+ ],
131
+ [
132
+ left[1][0] * right[0][0] + left[1][1] * right[1][0] + left[1][2] * right[2][0],
133
+ left[1][0] * right[0][1] + left[1][1] * right[1][1] + left[1][2] * right[2][1],
134
+ left[1][0] * right[0][2] + left[1][1] * right[1][2] + left[1][2] * right[2][2],
135
+ ],
136
+ [
137
+ left[2][0] * right[0][0] + left[2][1] * right[1][0] + left[2][2] * right[2][0],
138
+ left[2][0] * right[0][1] + left[2][1] * right[1][1] + left[2][2] * right[2][1],
139
+ left[2][0] * right[0][2] + left[2][1] * right[1][2] + left[2][2] * right[2][2],
140
+ ],
141
+ ];
142
+ }
143
+ function extractIntrinsicsFromTransformation(transformation) {
144
+ const sourceIntrinsicMatrix = toMatrix3x3(transformation?.sourceIntrinsicMatrix);
145
+ if (!sourceIntrinsicMatrix) {
146
+ return undefined;
147
+ }
148
+ const transformationMatrix = toMatrix3x3(transformation?.transformationMatrix);
149
+ const effectiveIntrinsicMatrix = transformationMatrix
150
+ ? multiply3x3(transformationMatrix, sourceIntrinsicMatrix)
151
+ : sourceIntrinsicMatrix;
152
+ const fx = effectiveIntrinsicMatrix[0][0];
153
+ const fy = effectiveIntrinsicMatrix[1][1];
154
+ const cx = effectiveIntrinsicMatrix[0][2];
155
+ const cy = effectiveIntrinsicMatrix[1][2];
156
+ if (![fx, fy, cx, cy].every((value) => Number.isFinite(value))) {
157
+ return undefined;
158
+ }
159
+ return {
160
+ left: {
161
+ focalLenght: { x: fx, y: fy },
162
+ principalPoint: { x: cx, y: cy },
163
+ },
164
+ right: {
165
+ focalLenght: { x: fx, y: fy },
166
+ principalPoint: { x: cx, y: cy },
167
+ },
168
+ };
169
+ }
170
+ function resolveRGBDIntrinsics(message, fallbackIntrinsics) {
171
+ return (extractIntrinsicsFromTransformation(message.depthImgFrame?.transformation) ??
172
+ extractIntrinsicsFromTransformation(message.depthEncodedFrame?.transformation) ??
173
+ extractIntrinsicsFromTransformation(message.colorImgFrame?.transformation) ??
174
+ extractIntrinsicsFromTransformation(message.colorEncodedFrame?.transformation) ??
175
+ fallbackIntrinsics);
176
+ }
177
+ async function extractEncodedColorFrame(encodedFrame, topicDecoders, topic) {
178
+ const decodeFrame = async () => await new Promise((resolve, reject) => {
179
+ const callback = (event) => {
180
+ resolve(event.message);
181
+ };
182
+ const rejectDecode = (error) => {
183
+ reject(error);
184
+ };
185
+ const args = {
186
+ topic,
187
+ message: encodedFrame,
188
+ callback,
189
+ };
190
+ if (encodedFrame.profile === Profile.AVC) {
191
+ void deserializeEncodedFrameH264({ ...args, topicDecoders, onError: rejectDecode }).catch(rejectDecode);
192
+ }
193
+ else if (encodedFrame.profile === Profile.JPEG) {
194
+ void deserializeMJPEGFrame(args).catch(rejectDecode);
195
+ }
196
+ else if (encodedFrame.profile === Profile.HEVC) {
197
+ void deserializeEncodedFrameH265({ ...args, topicDecoders, onError: rejectDecode }).catch(rejectDecode);
198
+ }
199
+ else {
200
+ reject(new Error(`Unsupported RGBD color profile ${Profile[encodedFrame.profile] ?? encodedFrame.profile}`));
201
+ }
202
+ });
203
+ const decoded = await decodeFrame();
204
+ return {
205
+ data: ensureEvenByteLength(decoded.data),
206
+ width: decoded.width,
207
+ height: decoded.height,
208
+ };
209
+ }
210
+ function extractColorFrame(encodedFrame, imageFrame, topicDecoders, topic) {
211
+ if (encodedFrame) {
212
+ return extractEncodedColorFrame(encodedFrame, topicDecoders, topic);
213
+ }
214
+ if (imageFrame) {
215
+ const { width, height, type } = parseMessage(imageFrame);
216
+ const specs = imageFrame.fb ?? imageFrame.sourceFb;
217
+ if (type === Type.NV12) {
218
+ const stride = specs?.stride || width;
219
+ const uvOffset = specs?.p1Offset || stride * height;
220
+ return Promise.resolve({
221
+ data: convertNv12ToI420(ensureEvenByteLength(imageFrame.data), width, height, stride, stride, 0, uvOffset),
222
+ width,
223
+ height,
224
+ });
225
+ }
226
+ if (type === Type.YUV420p) {
227
+ return Promise.resolve({
228
+ data: repackYuv420pToI420(imageFrame, width, height),
229
+ width,
230
+ height,
231
+ });
232
+ }
233
+ return Promise.reject(new Error(`Unsupported RGBD color ImgFrame type ${Type[type]}`));
234
+ }
235
+ return Promise.resolve({
236
+ data: new Uint8Array(),
237
+ width: 0,
238
+ height: 0,
239
+ });
240
+ }
241
+ function extractDepthFrame(encodedFrame, imageFrame) {
242
+ if (encodedFrame) {
243
+ return ensureEvenByteLength(encodedFrame.data);
244
+ }
245
+ if (imageFrame) {
246
+ return ensureEvenByteLength(imageFrame.data);
247
+ }
248
+ return new Uint8Array();
249
+ }
250
+ function parseDimensions(message) {
251
+ const obj = {
252
+ depthWidth: 0,
253
+ depthHeight: 0,
254
+ };
255
+ if (message.depthEncodedFrame) {
256
+ const { width, height } = message.depthEncodedFrame ?? { width: 1920, height: 1200 };
257
+ obj.depthWidth = width;
258
+ obj.depthHeight = height;
259
+ }
260
+ else if (message.depthImgFrame) {
261
+ const { width, height } = parseMessage(message.depthImgFrame);
262
+ obj.depthWidth = width;
263
+ obj.depthHeight = height;
264
+ }
265
+ return obj;
266
+ }
267
+ export async function deserializeRGBDFrameToPointCloud({ topic, topicDecoders, cameraIntrinsics, maxStereoDepth, message, callback, }) {
268
+ const workerSlot = getRGBDPointCloudWorkerSlot();
269
+ workerSlot.activeJobs += 1;
270
+ const { receiveTime } = parseMessage(message);
271
+ const { depthWidth, depthHeight } = parseDimensions(message);
272
+ const rgbdIntrinsics = resolveRGBDIntrinsics(message, cameraIntrinsics);
273
+ const hasGPU = await detectRGBDGPUSupport();
274
+ const colorFrame = await extractColorFrame(message.colorEncodedFrame, message.colorImgFrame, topicDecoders, topic);
275
+ const uint8DepthFrames = extractDepthFrame(message.depthEncodedFrame, message.depthImgFrame);
276
+ const depthFrames = uint8ArrayToUint16Array(uint8DepthFrames);
277
+ try {
278
+ const pointCloud = await workerSlot.remote.depthToPointcloudGPU([depthFrames], depthWidth, depthHeight, rgbdIntrinsics.right.focalLenght.x, rgbdIntrinsics.right.focalLenght.y, rgbdIntrinsics.right.principalPoint.x, rgbdIntrinsics.right.principalPoint.y, [colorFrame.data], colorFrame.width, colorFrame.height, maxStereoDepth, { hasGPU });
279
+ const foxgloveMessage = {
280
+ timestamp: message.tsDevice ?? receiveTime,
281
+ frame_id: `pointcloud-${topic}-frame`,
282
+ point_stride: 16,
283
+ pose: {
284
+ position: { x: 0, y: 0, z: 0 },
285
+ orientation: { x: 0, y: 0, z: 1, w: 0 }
286
+ },
287
+ width: depthWidth,
288
+ height: depthHeight,
289
+ fields: [
290
+ { name: "x", offset: 0, type: NumericType.FLOAT32 },
291
+ { name: "y", offset: 4, type: NumericType.FLOAT32 },
292
+ { name: "z", offset: 8, type: NumericType.FLOAT32 },
293
+ { name: "red", offset: 12, type: NumericType.UINT8 },
294
+ { name: "green", offset: 13, type: NumericType.UINT8 },
295
+ { name: "blue", offset: 14, type: NumericType.UINT8 },
296
+ { name: "alpha", offset: 15, type: NumericType.UINT8 },
297
+ ],
298
+ data: pointCloud[0]
299
+ };
300
+ callback({
301
+ topic,
302
+ receiveTime,
303
+ message: foxgloveMessage,
304
+ sizeInBytes: estimateObjectSize(foxgloveMessage),
305
+ schemaName: "foxglove.PointCloud.Colored"
306
+ });
307
+ if (message.depthImgFrame) {
308
+ void deserializeDepthFrame({
309
+ topic,
310
+ message: message.depthImgFrame,
311
+ callback,
312
+ maxStereoDepth: maxStereoDepth / 1000,
313
+ });
314
+ }
315
+ }
316
+ finally {
317
+ workerSlot.activeJobs = Math.max(0, workerSlot.activeJobs - 1);
318
+ }
319
+ }
320
+ //# sourceMappingURL=rgbd-to-pointcloud.js.map