@luxonis/visualizer-protobuf 3.1.12 → 3.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FoxgloveServer-Da9kV1cr.js → FoxgloveServer-CpnCBMeV.js} +1 -1
- package/dist/{communicator-Dh2aL-rj.js → communicator-DO6hmBxI.js} +1 -1
- package/dist/{depth-DiD1V2Sg.js → depth-Me_0Xnx6.js} +89 -2
- package/dist/{deserialization.worker-CxHfbNSI.js → deserialization.worker-CUrCdjHf.js} +435 -154
- package/dist/{foxglove-protocol-BtLMVx24.js → foxglove-protocol-SrBOBs-8.js} +1 -1
- package/dist/{index-B5oN0fQm.js → index-5ZSfZI8d.js} +1 -1
- package/dist/{index-yO9F9DL5.js → index-B8aafdRQ.js} +5 -5
- package/dist/{index-gafqmUmi.js → index-BMew9qiQ.js} +57 -126
- package/dist/{index-BydKxany.js → index-BsIRFSYD.js} +36 -9
- package/dist/{index-B8JZ9tAh.js → index-CIhAU5Cs.js} +5 -5
- package/dist/{index-DuP_Wg3E.js → index-CN6tI-uI.js} +5 -5
- package/dist/{index-BFAcwVLJ.js → index-CQtXiN8I.js} +5 -5
- package/dist/{index-C-n27_wk.js → index-CZGEFE1k.js} +5 -5
- package/dist/{index-O1aT66OM.js → index-CeRrHeG_.js} +5 -5
- package/dist/{index-BtMMMbp8.js → index-CqH6rdRP.js} +5 -5
- package/dist/{index-CVrY6MoS.js → index-CrPun-aU.js} +5 -5
- package/dist/{index-9Qz76jnn.js → index-Dc3rS1Cf.js} +7 -7
- package/dist/{index-RxEWv1Fn.js → index-DgNYLOM9.js} +5 -5
- package/dist/{index-8bTMarZg.js → index-DjRF0u25.js} +5 -5
- package/dist/{index-CwAmHvi3.js → index-Dmc1065I.js} +5 -5
- package/dist/{index-BvC_JYBX.js → index-Dn6pTTdu.js} +5 -5
- package/dist/{index-DXdd6C_Q.js → index-N2I7Bhtx.js} +5 -5
- package/dist/{index-CQhsew4_.js → index-_Z7btKy-.js} +5 -5
- package/dist/{index-D_TjqfY9.js → index-_ggcs841.js} +5 -5
- package/dist/{index-oyn_LQK1.js → index-svPKcEP3.js} +5 -5
- package/dist/{index-DnaaNoIT.js → index-u1cGSF5c.js} +5 -5
- package/dist/index.js +5 -5
- package/dist/lib/src/components/PanelToolbar.d.ts.map +1 -1
- package/dist/lib/src/components/PanelToolbar.js +2 -2
- package/dist/lib/src/components/PanelToolbar.js.map +1 -1
- package/dist/lib/src/connection/foxglove-connection.d.ts.map +1 -1
- package/dist/lib/src/connection/foxglove-connection.js +12 -2
- package/dist/lib/src/connection/foxglove-connection.js.map +1 -1
- package/dist/lib/src/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js +59 -20
- package/dist/lib/src/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js.map +1 -1
- package/dist/lib/src/messaging/deserialization/pointcloud/utils.d.ts.map +1 -1
- package/dist/lib/src/messaging/deserialization/pointcloud/utils.js.map +1 -1
- package/dist/lib/src/messaging/deserialization/video/h264.d.ts +4 -1
- package/dist/lib/src/messaging/deserialization/video/h264.d.ts.map +1 -1
- package/dist/lib/src/messaging/deserialization/video/h264.js +25 -13
- package/dist/lib/src/messaging/deserialization/video/h264.js.map +1 -1
- package/dist/lib/src/messaging/deserialization/video/h265.d.ts +3 -0
- package/dist/lib/src/messaging/deserialization/video/h265.d.ts.map +1 -1
- package/dist/lib/src/messaging/deserialization/video/h265.js +21 -9
- package/dist/lib/src/messaging/deserialization/video/h265.js.map +1 -1
- package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.d.ts +5 -5
- package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.d.ts.map +1 -1
- package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.js +362 -91
- package/dist/lib/src/messaging/deserialization/video/rgbd-to-pointcloud.js.map +1 -1
- package/dist/lib/src/messaging/protobuf.d.ts +2 -2
- package/dist/lib/src/messaging/protobuf.d.ts.map +1 -1
- package/dist/lib/src/messaging/protobuf.js +3 -3
- package/dist/lib/src/messaging/protobuf.js.map +1 -1
- package/dist/lib/src/utils/poitcloud-sync.d.ts +7 -2
- package/dist/lib/src/utils/poitcloud-sync.d.ts.map +1 -1
- package/dist/lib/src/utils/poitcloud-sync.js +10 -6
- package/dist/lib/src/utils/poitcloud-sync.js.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.d.ts.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.js +7 -2
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.js.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.d.ts.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js +33 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js.map +1 -1
- package/dist/{pointcloudFromDepth.worker-60RA4Ief.js → pointcloudFromDepth.worker-wzSOsJVb.js} +86 -47
- package/dist/{protobuf-OcbVtxg1.js → protobuf-CKMA2Rn8.js} +214 -214
- package/dist/{worker-C2MHIq3t.js → worker-Bhe7uYcO.js} +4 -4
- package/dist/{worker-Be-hru8f.js → worker-VIU0v1ZW.js} +3 -3
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { b as _objectSpread2, P as PointsAnnotationType, T as Type, h as Profile, p as protobufsBySchema } from './protobuf-
|
|
3
|
-
import { w as wrap, e as expose } from './comlink-jf8bdrAf.js';
|
|
4
|
-
import { t as typescript } from './index-
|
|
5
|
-
import {
|
|
2
|
+
import { b as _objectSpread2, P as PointsAnnotationType, T as Type, h as Profile, p as protobufsBySchema } from './protobuf-CKMA2Rn8.js';
|
|
3
|
+
import { w as wrap, r as releaseProxy, e as expose } from './comlink-jf8bdrAf.js';
|
|
4
|
+
import { t as typescript } from './index-5ZSfZI8d.js';
|
|
5
|
+
import { Z as parseMessage, e as estimateObjectSize, _ as fromMillis, $ as DecoderRuntimeError, d as dist, a0 as deserializeDepthFrame, f as globalRenderMetricsManager, c as constructKeyForTopicRenderMetrics, g as globalInputEventMetricsManager, a as globalDecodeMetricsManager, a1 as UnsupportedTopicError, a2 as NotInSecureContextError, a3 as EncodedStreamNotSupportedError } from './depth-Me_0Xnx6.js';
|
|
6
6
|
import { L as Logger } from './logger-Bqy1nuLj.js';
|
|
7
7
|
import { i as isCapableOfEncodedStream } from './encoding-jXImCIb4.js';
|
|
8
8
|
import { u as uint8ArrayToUint16Array } from './utils-DmlHZWuo.js';
|
|
@@ -822,6 +822,7 @@ function closeTopicDecoder$1(topic, topicDecoders) {
|
|
|
822
822
|
closeDecoder$1(decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.decoder);
|
|
823
823
|
decoderInfo === null || decoderInfo === void 0 || decoderInfo.timing.clear();
|
|
824
824
|
decoderInfo === null || decoderInfo === void 0 || decoderInfo.transformations.clear();
|
|
825
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.pendingCallbacks.clear();
|
|
825
826
|
}
|
|
826
827
|
function isIgnorableInitialDecodeError(error) {
|
|
827
828
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -932,7 +933,7 @@ function repackI420(source, width, height, yLayout, uLayout, vLayout, cropLeft =
|
|
|
932
933
|
}
|
|
933
934
|
return out;
|
|
934
935
|
}
|
|
935
|
-
async function copyVideoFrameToI420(frame,
|
|
936
|
+
async function copyVideoFrameToI420(frame, _logPrefix) {
|
|
936
937
|
var _visibleRect$width, _visibleRect$height, _visibleRect$x, _visibleRect$y;
|
|
937
938
|
const visibleRect = frame.visibleRect;
|
|
938
939
|
const frameWidth = (_visibleRect$width = visibleRect === null || visibleRect === void 0 ? void 0 : visibleRect.width) !== null && _visibleRect$width !== void 0 ? _visibleRect$width : frame.codedWidth;
|
|
@@ -940,7 +941,6 @@ async function copyVideoFrameToI420(frame, logPrefix) {
|
|
|
940
941
|
const cropLeft = (_visibleRect$x = visibleRect === null || visibleRect === void 0 ? void 0 : visibleRect.x) !== null && _visibleRect$x !== void 0 ? _visibleRect$x : 0;
|
|
941
942
|
const cropTop = (_visibleRect$y = visibleRect === null || visibleRect === void 0 ? void 0 : visibleRect.y) !== null && _visibleRect$y !== void 0 ? _visibleRect$y : 0;
|
|
942
943
|
let finalBuffer = new Uint8Array(frame.allocationSize());
|
|
943
|
-
logger$2.warn(`${logPrefix} decoder output format: ${frame.format}, coded=${frame.codedWidth}x${frame.codedHeight}, display=${frame.displayWidth}x${frame.displayHeight}, visible=${frameWidth}x${frameHeight}@${cropLeft},${cropTop}`);
|
|
944
944
|
switch (frame.format) {
|
|
945
945
|
case "I420":
|
|
946
946
|
{
|
|
@@ -967,13 +967,9 @@ async function copyVideoFrameToI420(frame, logPrefix) {
|
|
|
967
967
|
var _layout$stride;
|
|
968
968
|
const packedBuffer = new Uint8Array(frame.allocationSize());
|
|
969
969
|
const [layout] = await frame.copyTo(packedBuffer);
|
|
970
|
-
logger$2.warn(`${logPrefix} decoder received ${frame.format} frame.`);
|
|
971
970
|
finalBuffer = packedToI420(packedBuffer, frameWidth, frameHeight, (_layout$stride = layout === null || layout === void 0 ? void 0 : layout.stride) !== null && _layout$stride !== void 0 ? _layout$stride : frame.codedWidth * 4, frame.format, cropLeft, cropTop);
|
|
972
971
|
break;
|
|
973
972
|
}
|
|
974
|
-
default:
|
|
975
|
-
logger$2.warn(`${logPrefix} decoder received unexpected frame format:`, frame.format);
|
|
976
|
-
break;
|
|
977
973
|
}
|
|
978
974
|
return {
|
|
979
975
|
data: finalBuffer,
|
|
@@ -983,23 +979,25 @@ async function copyVideoFrameToI420(frame, logPrefix) {
|
|
|
983
979
|
}
|
|
984
980
|
function createVideoDecoder$1({
|
|
985
981
|
topic,
|
|
986
|
-
|
|
987
|
-
topicDecoders,
|
|
988
|
-
onError
|
|
982
|
+
topicDecoders
|
|
989
983
|
}) {
|
|
990
984
|
let hasProducedFrame = false;
|
|
991
985
|
return new VideoDecoder({
|
|
992
986
|
output: async frame => {
|
|
993
|
-
var
|
|
987
|
+
var _decoderInfo$timing$g, _decoderInfo$pendingC;
|
|
994
988
|
hasProducedFrame = true;
|
|
995
989
|
const {
|
|
996
990
|
data: finalBuffer,
|
|
997
991
|
width: frameWidth,
|
|
998
992
|
height: frameHeight
|
|
999
|
-
} = await copyVideoFrameToI420(frame
|
|
1000
|
-
const
|
|
1001
|
-
const
|
|
1002
|
-
|
|
993
|
+
} = await copyVideoFrameToI420(frame);
|
|
994
|
+
const decoderInfo = topicDecoders.get(topic);
|
|
995
|
+
const receiveTime = (_decoderInfo$timing$g = decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.timing.get(frame.timestamp)) !== null && _decoderInfo$timing$g !== void 0 ? _decoderInfo$timing$g : dist.fromMicros(frame.timestamp);
|
|
996
|
+
const transformation = decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.transformations.get(frame.timestamp);
|
|
997
|
+
const callback = (_decoderInfo$pendingC = decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.pendingCallbacks.get(frame.timestamp)) !== null && _decoderInfo$pendingC !== void 0 ? _decoderInfo$pendingC : decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.callback;
|
|
998
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.timing.delete(frame.timestamp);
|
|
999
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.transformations.delete(frame.timestamp);
|
|
1000
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.pendingCallbacks.delete(frame.timestamp);
|
|
1003
1001
|
const foxgloveMessage = {
|
|
1004
1002
|
timestamp: receiveTime,
|
|
1005
1003
|
frame_id: `h264-${topic}-frame`,
|
|
@@ -1009,7 +1007,7 @@ function createVideoDecoder$1({
|
|
|
1009
1007
|
encoding: "yuv420p",
|
|
1010
1008
|
step: frameWidth
|
|
1011
1009
|
};
|
|
1012
|
-
callback({
|
|
1010
|
+
callback === null || callback === void 0 || callback({
|
|
1013
1011
|
topic,
|
|
1014
1012
|
receiveTime,
|
|
1015
1013
|
message: foxgloveMessage,
|
|
@@ -1020,6 +1018,7 @@ function createVideoDecoder$1({
|
|
|
1020
1018
|
frame.close();
|
|
1021
1019
|
},
|
|
1022
1020
|
error: error => {
|
|
1021
|
+
var _topicDecoders$get;
|
|
1023
1022
|
if (!hasProducedFrame && isIgnorableInitialDecodeError(error)) {
|
|
1024
1023
|
logger$2.warn(`Ignoring initial H264 decoder error for topic ${topic}: ${error.message}`);
|
|
1025
1024
|
closeTopicDecoder$1(topic, topicDecoders);
|
|
@@ -1027,7 +1026,7 @@ function createVideoDecoder$1({
|
|
|
1027
1026
|
}
|
|
1028
1027
|
logger$2.error(error);
|
|
1029
1028
|
closeTopicDecoder$1(topic, topicDecoders);
|
|
1030
|
-
onError(new DecoderRuntimeError(topic, error.message));
|
|
1029
|
+
(_topicDecoders$get = topicDecoders.get(topic)) === null || _topicDecoders$get === void 0 || _topicDecoders$get.onError(new DecoderRuntimeError(topic, error.message));
|
|
1031
1030
|
}
|
|
1032
1031
|
});
|
|
1033
1032
|
}
|
|
@@ -1049,9 +1048,7 @@ async function deserializeEncodedFrameH264({
|
|
|
1049
1048
|
if (!existingDecoderInfo || existingDecoderInfo.decoder.state === "closed") {
|
|
1050
1049
|
const decoder = createVideoDecoder$1({
|
|
1051
1050
|
topic,
|
|
1052
|
-
|
|
1053
|
-
topicDecoders,
|
|
1054
|
-
onError
|
|
1051
|
+
topicDecoders
|
|
1055
1052
|
});
|
|
1056
1053
|
try {
|
|
1057
1054
|
configureDecoder(decoder);
|
|
@@ -1064,11 +1061,17 @@ async function deserializeEncodedFrameH264({
|
|
|
1064
1061
|
existingDecoderInfo.decoder = decoder;
|
|
1065
1062
|
existingDecoderInfo.timing.clear();
|
|
1066
1063
|
existingDecoderInfo.transformations.clear();
|
|
1064
|
+
existingDecoderInfo.pendingCallbacks.clear();
|
|
1065
|
+
existingDecoderInfo.callback = callback;
|
|
1066
|
+
existingDecoderInfo.onError = onError;
|
|
1067
1067
|
} else {
|
|
1068
1068
|
topicDecoders.set(topic, {
|
|
1069
1069
|
decoder,
|
|
1070
1070
|
timing: new Map(),
|
|
1071
|
-
transformations: new Map()
|
|
1071
|
+
transformations: new Map(),
|
|
1072
|
+
pendingCallbacks: new Map(),
|
|
1073
|
+
callback,
|
|
1074
|
+
onError
|
|
1072
1075
|
});
|
|
1073
1076
|
}
|
|
1074
1077
|
} else if (existingDecoderInfo.decoder.state === "unconfigured") {
|
|
@@ -1076,6 +1079,9 @@ async function deserializeEncodedFrameH264({
|
|
|
1076
1079
|
configureDecoder(existingDecoderInfo.decoder);
|
|
1077
1080
|
existingDecoderInfo.timing.clear();
|
|
1078
1081
|
existingDecoderInfo.transformations.clear();
|
|
1082
|
+
existingDecoderInfo.pendingCallbacks.clear();
|
|
1083
|
+
existingDecoderInfo.callback = callback;
|
|
1084
|
+
existingDecoderInfo.onError = onError;
|
|
1079
1085
|
} catch (error) {
|
|
1080
1086
|
closeTopicDecoder$1(topic, topicDecoders);
|
|
1081
1087
|
onError(new DecoderRuntimeError(topic, error instanceof Error ? error.message : "Failed to reconfigure H.264 decoder."));
|
|
@@ -1086,6 +1092,8 @@ async function deserializeEncodedFrameH264({
|
|
|
1086
1092
|
if (!decoderInfo) {
|
|
1087
1093
|
return;
|
|
1088
1094
|
}
|
|
1095
|
+
decoderInfo.callback = callback;
|
|
1096
|
+
decoderInfo.onError = onError;
|
|
1089
1097
|
if (decoderInfo.decoder.decodeQueueSize > 60) {
|
|
1090
1098
|
decoderInfo.decoder.reset();
|
|
1091
1099
|
decoderInfo.timing.clear();
|
|
@@ -1095,6 +1103,7 @@ async function deserializeEncodedFrameH264({
|
|
|
1095
1103
|
const microTimestamp = receiveTime.sec * 1000000 + Math.floor(receiveTime.nsec / 1000);
|
|
1096
1104
|
decoderInfo.timing.set(microTimestamp, receiveTime);
|
|
1097
1105
|
decoderInfo.transformations.set(microTimestamp, message.transformation);
|
|
1106
|
+
decoderInfo.pendingCallbacks.set(microTimestamp, callback);
|
|
1098
1107
|
const frame = {
|
|
1099
1108
|
type: 'key',
|
|
1100
1109
|
data: message.data,
|
|
@@ -1136,24 +1145,27 @@ function closeTopicDecoder(topic, topicDecoders) {
|
|
|
1136
1145
|
closeDecoder(decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.decoder);
|
|
1137
1146
|
decoderInfo === null || decoderInfo === void 0 || decoderInfo.timing.clear();
|
|
1138
1147
|
decoderInfo === null || decoderInfo === void 0 || decoderInfo.transformations.clear();
|
|
1148
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.pendingCallbacks.clear();
|
|
1139
1149
|
}
|
|
1140
1150
|
function createVideoDecoder({
|
|
1141
1151
|
topic,
|
|
1142
|
-
|
|
1143
|
-
topicDecoders,
|
|
1144
|
-
onError
|
|
1152
|
+
topicDecoders
|
|
1145
1153
|
}) {
|
|
1146
1154
|
return new VideoDecoder({
|
|
1147
1155
|
output: async frame => {
|
|
1148
|
-
var
|
|
1156
|
+
var _decoderInfo$timing$g, _decoderInfo$pendingC;
|
|
1149
1157
|
const {
|
|
1150
1158
|
data: buffer,
|
|
1151
1159
|
width,
|
|
1152
1160
|
height
|
|
1153
|
-
} = await copyVideoFrameToI420(frame
|
|
1154
|
-
const
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1161
|
+
} = await copyVideoFrameToI420(frame);
|
|
1162
|
+
const decoderInfo = topicDecoders.get(topic);
|
|
1163
|
+
const receiveTime = (_decoderInfo$timing$g = decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.timing.get(frame.timestamp)) !== null && _decoderInfo$timing$g !== void 0 ? _decoderInfo$timing$g : dist.fromMicros(frame.timestamp);
|
|
1164
|
+
const transformation = decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.transformations.get(frame.timestamp);
|
|
1165
|
+
const callback = (_decoderInfo$pendingC = decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.pendingCallbacks.get(frame.timestamp)) !== null && _decoderInfo$pendingC !== void 0 ? _decoderInfo$pendingC : decoderInfo === null || decoderInfo === void 0 ? void 0 : decoderInfo.callback;
|
|
1166
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.timing.delete(frame.timestamp);
|
|
1167
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.transformations.delete(frame.timestamp);
|
|
1168
|
+
decoderInfo === null || decoderInfo === void 0 || decoderInfo.pendingCallbacks.delete(frame.timestamp);
|
|
1157
1169
|
const foxgloveMessage = {
|
|
1158
1170
|
timestamp: receiveTime,
|
|
1159
1171
|
frame_id: `h265-${topic}-frame`,
|
|
@@ -1163,7 +1175,7 @@ function createVideoDecoder({
|
|
|
1163
1175
|
encoding: "yuv420p",
|
|
1164
1176
|
step: width
|
|
1165
1177
|
};
|
|
1166
|
-
callback({
|
|
1178
|
+
callback === null || callback === void 0 || callback({
|
|
1167
1179
|
topic,
|
|
1168
1180
|
receiveTime,
|
|
1169
1181
|
message: foxgloveMessage,
|
|
@@ -1174,9 +1186,10 @@ function createVideoDecoder({
|
|
|
1174
1186
|
frame.close();
|
|
1175
1187
|
},
|
|
1176
1188
|
error: error => {
|
|
1189
|
+
var _topicDecoders$get;
|
|
1177
1190
|
logger$1.error(error);
|
|
1178
1191
|
closeTopicDecoder(topic, topicDecoders);
|
|
1179
|
-
onError(new DecoderRuntimeError(topic, error.message));
|
|
1192
|
+
(_topicDecoders$get = topicDecoders.get(topic)) === null || _topicDecoders$get === void 0 || _topicDecoders$get.onError(new DecoderRuntimeError(topic, error.message));
|
|
1180
1193
|
}
|
|
1181
1194
|
});
|
|
1182
1195
|
}
|
|
@@ -1198,9 +1211,7 @@ async function deserializeEncodedFrameH265({
|
|
|
1198
1211
|
if (!existingDecoderInfo || existingDecoderInfo.decoder.state === "closed") {
|
|
1199
1212
|
const decoder = createVideoDecoder({
|
|
1200
1213
|
topic,
|
|
1201
|
-
|
|
1202
|
-
topicDecoders,
|
|
1203
|
-
onError
|
|
1214
|
+
topicDecoders
|
|
1204
1215
|
});
|
|
1205
1216
|
try {
|
|
1206
1217
|
decoder.configure({
|
|
@@ -1216,11 +1227,17 @@ async function deserializeEncodedFrameH265({
|
|
|
1216
1227
|
existingDecoderInfo.decoder = decoder;
|
|
1217
1228
|
existingDecoderInfo.timing.clear();
|
|
1218
1229
|
existingDecoderInfo.transformations.clear();
|
|
1230
|
+
existingDecoderInfo.pendingCallbacks.clear();
|
|
1231
|
+
existingDecoderInfo.callback = callback;
|
|
1232
|
+
existingDecoderInfo.onError = onError;
|
|
1219
1233
|
} else {
|
|
1220
1234
|
topicDecoders.set(topic, {
|
|
1221
1235
|
decoder,
|
|
1222
1236
|
timing: new Map(),
|
|
1223
|
-
transformations: new Map()
|
|
1237
|
+
transformations: new Map(),
|
|
1238
|
+
pendingCallbacks: new Map(),
|
|
1239
|
+
callback,
|
|
1240
|
+
onError
|
|
1224
1241
|
});
|
|
1225
1242
|
}
|
|
1226
1243
|
}
|
|
@@ -1228,6 +1245,8 @@ async function deserializeEncodedFrameH265({
|
|
|
1228
1245
|
if (!decoderInfo) {
|
|
1229
1246
|
return;
|
|
1230
1247
|
}
|
|
1248
|
+
decoderInfo.callback = callback;
|
|
1249
|
+
decoderInfo.onError = onError;
|
|
1231
1250
|
if (decoderInfo.decoder.decodeQueueSize > 60) {
|
|
1232
1251
|
decoderInfo.decoder.reset();
|
|
1233
1252
|
return;
|
|
@@ -1235,6 +1254,7 @@ async function deserializeEncodedFrameH265({
|
|
|
1235
1254
|
const microTimestamp = receiveTime.sec * 1000000 + Math.floor(receiveTime.nsec / 1000);
|
|
1236
1255
|
decoderInfo.timing.set(microTimestamp, receiveTime);
|
|
1237
1256
|
decoderInfo.transformations.set(microTimestamp, message.transformation);
|
|
1257
|
+
decoderInfo.pendingCallbacks.set(microTimestamp, callback);
|
|
1238
1258
|
const frame = {
|
|
1239
1259
|
type: 'key',
|
|
1240
1260
|
data: message.data,
|
|
@@ -1276,7 +1296,7 @@ async function deserializeMJPEGFrame({
|
|
|
1276
1296
|
data: buffer,
|
|
1277
1297
|
width,
|
|
1278
1298
|
height
|
|
1279
|
-
} = await copyVideoFrameToI420(frame
|
|
1299
|
+
} = await copyVideoFrameToI420(frame);
|
|
1280
1300
|
const foxgloveMessage = {
|
|
1281
1301
|
timestamp: receiveTime,
|
|
1282
1302
|
frame_id: "camera",
|
|
@@ -1297,12 +1317,19 @@ async function deserializeMJPEGFrame({
|
|
|
1297
1317
|
});
|
|
1298
1318
|
}
|
|
1299
1319
|
|
|
1300
|
-
const RGBD_POINTCLOUD_WORKER_COUNT =
|
|
1320
|
+
const RGBD_POINTCLOUD_WORKER_COUNT = 6;
|
|
1321
|
+
const RGBD_POINTCLOUD_WORKER_TIMEOUT_MS = 15000;
|
|
1322
|
+
const RGBD_POINTCLOUD_SCHEDULE_DELAY_MS = 0;
|
|
1323
|
+
const RGBD_GPU_BATCH_SIZE = 2;
|
|
1324
|
+
const RGBD_GPU_BATCH_FLUSH_DELAY_MS = 8;
|
|
1325
|
+
const RGBD_POINTCLOUD_IDLE_CLEANUP_MS = 30000;
|
|
1301
1326
|
let cachedRGBDHasGPU;
|
|
1302
1327
|
let rgbdHasGPUPromise;
|
|
1303
1328
|
let rgbdPointCloudWorkers;
|
|
1304
1329
|
let rgbdPointCloudWorkerIndex = 0;
|
|
1305
|
-
|
|
1330
|
+
let rgbdPointCloudIdleCleanupTimeoutId;
|
|
1331
|
+
const rgbdIntrinsicsByTopic = new Map();
|
|
1332
|
+
const pendingRGBDBatches = new Map();
|
|
1306
1333
|
function ensureEvenByteLength(data) {
|
|
1307
1334
|
if (data.length % 2 === 0) {
|
|
1308
1335
|
return data;
|
|
@@ -1311,12 +1338,9 @@ function ensureEvenByteLength(data) {
|
|
|
1311
1338
|
padded.set(data);
|
|
1312
1339
|
return padded;
|
|
1313
1340
|
}
|
|
1314
|
-
|
|
1315
|
-
if (cachedRGBDHasGPU != undefined) {
|
|
1316
|
-
return
|
|
1317
|
-
}
|
|
1318
|
-
if (rgbdHasGPUPromise) {
|
|
1319
|
-
return await rgbdHasGPUPromise;
|
|
1341
|
+
function ensureRGBDGPUSupportDetection() {
|
|
1342
|
+
if (cachedRGBDHasGPU != undefined || rgbdHasGPUPromise) {
|
|
1343
|
+
return;
|
|
1320
1344
|
}
|
|
1321
1345
|
rgbdHasGPUPromise = (async () => {
|
|
1322
1346
|
if (typeof navigator.gpu === "undefined") {
|
|
@@ -1327,53 +1351,116 @@ async function detectRGBDGPUSupport() {
|
|
|
1327
1351
|
const adapter = await navigator.gpu.requestAdapter();
|
|
1328
1352
|
cachedRGBDHasGPU = adapter != undefined;
|
|
1329
1353
|
return cachedRGBDHasGPU;
|
|
1330
|
-
} catch (
|
|
1354
|
+
} catch (error) {
|
|
1331
1355
|
cachedRGBDHasGPU = false;
|
|
1332
1356
|
return false;
|
|
1333
1357
|
} finally {
|
|
1334
1358
|
rgbdHasGPUPromise = undefined;
|
|
1335
1359
|
}
|
|
1336
1360
|
})();
|
|
1337
|
-
return await rgbdHasGPUPromise;
|
|
1338
1361
|
}
|
|
1339
|
-
function
|
|
1362
|
+
function getRGBDGPUSupport() {
|
|
1363
|
+
ensureRGBDGPUSupportDetection();
|
|
1364
|
+
return cachedRGBDHasGPU !== null && cachedRGBDHasGPU !== void 0 ? cachedRGBDHasGPU : false;
|
|
1365
|
+
}
|
|
1366
|
+
function ensureRGBDPointCloudWorkers() {
|
|
1340
1367
|
if (!rgbdPointCloudWorkers) {
|
|
1341
1368
|
rgbdPointCloudWorkers = Array.from({
|
|
1342
1369
|
length: RGBD_POINTCLOUD_WORKER_COUNT
|
|
1343
1370
|
}, () => {
|
|
1344
|
-
|
|
1345
|
-
type: "module"
|
|
1346
|
-
});
|
|
1347
|
-
return {
|
|
1348
|
-
worker,
|
|
1349
|
-
remote: wrap(worker),
|
|
1350
|
-
activeJobs: 0
|
|
1351
|
-
};
|
|
1371
|
+
return createRGBDPointCloudWorkerSlot();
|
|
1352
1372
|
});
|
|
1353
1373
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
if (left.slot.activeJobs !== right.slot.activeJobs) {
|
|
1360
|
-
return left.slot.activeJobs - right.slot.activeJobs;
|
|
1361
|
-
}
|
|
1362
|
-
const leftDistance = (left.index - rgbdPointCloudWorkerIndex + slots.length) % slots.length;
|
|
1363
|
-
const rightDistance = (right.index - rgbdPointCloudWorkerIndex + slots.length) % slots.length;
|
|
1364
|
-
return leftDistance - rightDistance;
|
|
1374
|
+
return rgbdPointCloudWorkers;
|
|
1375
|
+
}
|
|
1376
|
+
function createRGBDPointCloudWorkerSlot() {
|
|
1377
|
+
const worker = new Worker(new URL("pointcloudFromDepth.worker-wzSOsJVb.js", import.meta.url), {
|
|
1378
|
+
type: "module"
|
|
1365
1379
|
});
|
|
1366
|
-
const
|
|
1367
|
-
|
|
1368
|
-
|
|
1380
|
+
const remote = wrap(worker);
|
|
1381
|
+
return {
|
|
1382
|
+
worker,
|
|
1383
|
+
remote,
|
|
1384
|
+
activeJobs: 0,
|
|
1385
|
+
dispose: () => {
|
|
1386
|
+
remote[releaseProxy]();
|
|
1387
|
+
worker.terminate();
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
1391
|
+
function clearRGBDPointCloudIdleCleanupTimeout() {
|
|
1392
|
+
if (rgbdPointCloudIdleCleanupTimeoutId != undefined) {
|
|
1393
|
+
clearTimeout(rgbdPointCloudIdleCleanupTimeoutId);
|
|
1394
|
+
rgbdPointCloudIdleCleanupTimeoutId = undefined;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
function hasActiveRGBDPointCloudWork() {
|
|
1398
|
+
var _rgbdPointCloudWorker, _rgbdPointCloudWorker2;
|
|
1399
|
+
const hasActiveJobs = (_rgbdPointCloudWorker = (_rgbdPointCloudWorker2 = rgbdPointCloudWorkers) === null || _rgbdPointCloudWorker2 === void 0 ? void 0 : _rgbdPointCloudWorker2.some(slot => slot.activeJobs > 0)) !== null && _rgbdPointCloudWorker !== void 0 ? _rgbdPointCloudWorker : false;
|
|
1400
|
+
return hasActiveJobs || pendingRGBDBatches.size > 0;
|
|
1401
|
+
}
|
|
1402
|
+
function disposeRGBDPointCloudWorkers() {
|
|
1403
|
+
clearRGBDPointCloudIdleCleanupTimeout();
|
|
1404
|
+
for (const batch of pendingRGBDBatches.values()) {
|
|
1405
|
+
clearRGBDBatchFlush(batch);
|
|
1406
|
+
}
|
|
1407
|
+
pendingRGBDBatches.clear();
|
|
1408
|
+
rgbdIntrinsicsByTopic.clear();
|
|
1409
|
+
if (rgbdPointCloudWorkers) {
|
|
1410
|
+
for (const slot of rgbdPointCloudWorkers) {
|
|
1411
|
+
slot.dispose();
|
|
1412
|
+
}
|
|
1413
|
+
rgbdPointCloudWorkers = undefined;
|
|
1414
|
+
}
|
|
1415
|
+
rgbdPointCloudWorkerIndex = 0;
|
|
1416
|
+
}
|
|
1417
|
+
function scheduleRGBDPointCloudWorkersCleanup() {
|
|
1418
|
+
clearRGBDPointCloudIdleCleanupTimeout();
|
|
1419
|
+
rgbdPointCloudIdleCleanupTimeoutId = setTimeout(() => {
|
|
1420
|
+
if (hasActiveRGBDPointCloudWork()) {
|
|
1421
|
+
scheduleRGBDPointCloudWorkersCleanup();
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
disposeRGBDPointCloudWorkers();
|
|
1425
|
+
}, RGBD_POINTCLOUD_IDLE_CLEANUP_MS);
|
|
1426
|
+
}
|
|
1427
|
+
function markRGBDPointCloudWorkersActive() {
|
|
1428
|
+
scheduleRGBDPointCloudWorkersCleanup();
|
|
1429
|
+
}
|
|
1430
|
+
function replaceRGBDPointCloudWorker(index) {
|
|
1431
|
+
const slots = ensureRGBDPointCloudWorkers();
|
|
1432
|
+
const currentSlot = slots[index];
|
|
1433
|
+
currentSlot === null || currentSlot === void 0 || currentSlot.dispose();
|
|
1434
|
+
const replacementSlot = createRGBDPointCloudWorkerSlot();
|
|
1435
|
+
slots[index] = replacementSlot;
|
|
1436
|
+
markRGBDPointCloudWorkersActive();
|
|
1437
|
+
return replacementSlot;
|
|
1438
|
+
}
|
|
1439
|
+
function tryAcquireRGBDPointCloudWorkerSlot() {
|
|
1440
|
+
const ensuredSlots = ensureRGBDPointCloudWorkers();
|
|
1441
|
+
markRGBDPointCloudWorkersActive();
|
|
1442
|
+
for (let offset = 0; offset < ensuredSlots.length; offset++) {
|
|
1443
|
+
const index = (rgbdPointCloudWorkerIndex + offset) % ensuredSlots.length;
|
|
1444
|
+
const slot = ensuredSlots[index];
|
|
1445
|
+
if (!slot || slot.activeJobs > 0) {
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
slot.activeJobs = 1;
|
|
1449
|
+
rgbdPointCloudWorkerIndex = (index + 1) % ensuredSlots.length;
|
|
1450
|
+
return {
|
|
1451
|
+
slot,
|
|
1452
|
+
index
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
return undefined;
|
|
1369
1456
|
}
|
|
1370
1457
|
function repackYuv420pToI420(imageFrame, width, height) {
|
|
1371
1458
|
var _imageFrame$fb;
|
|
1372
1459
|
const specs = (_imageFrame$fb = imageFrame.fb) !== null && _imageFrame$fb !== void 0 ? _imageFrame$fb : imageFrame.sourceFb;
|
|
1373
1460
|
const source = ensureEvenByteLength(imageFrame.data);
|
|
1374
1461
|
const yStride = (specs === null || specs === void 0 ? void 0 : specs.stride) || width;
|
|
1375
|
-
const uvWidth = Math.
|
|
1376
|
-
const uvHeight = Math.
|
|
1462
|
+
const uvWidth = Math.ceil(width / 2);
|
|
1463
|
+
const uvHeight = Math.ceil(height / 2);
|
|
1377
1464
|
const uvStride = yStride > width ? Math.floor(yStride / 2) : uvWidth;
|
|
1378
1465
|
const yPlaneSize = width * height;
|
|
1379
1466
|
const uvPlaneSize = uvWidth * uvHeight;
|
|
@@ -1445,9 +1532,21 @@ function extractIntrinsicsFromTransformation(transformation) {
|
|
|
1445
1532
|
}
|
|
1446
1533
|
};
|
|
1447
1534
|
}
|
|
1448
|
-
function
|
|
1449
|
-
var _ref, _ref2,
|
|
1450
|
-
return (_ref = (_ref2 = (
|
|
1535
|
+
function resolveRGBDIntrinsicsFromMessage(message) {
|
|
1536
|
+
var _ref, _ref2, _extractIntrinsicsFro, _message$depthImgFram, _message$depthEncoded, _message$colorImgFram, _message$colorEncoded;
|
|
1537
|
+
return (_ref = (_ref2 = (_extractIntrinsicsFro = extractIntrinsicsFromTransformation((_message$depthImgFram = message.depthImgFrame) === null || _message$depthImgFram === void 0 ? void 0 : _message$depthImgFram.transformation)) !== null && _extractIntrinsicsFro !== void 0 ? _extractIntrinsicsFro : extractIntrinsicsFromTransformation((_message$depthEncoded = message.depthEncodedFrame) === null || _message$depthEncoded === void 0 ? void 0 : _message$depthEncoded.transformation)) !== null && _ref2 !== void 0 ? _ref2 : extractIntrinsicsFromTransformation((_message$colorImgFram = message.colorImgFrame) === null || _message$colorImgFram === void 0 ? void 0 : _message$colorImgFram.transformation)) !== null && _ref !== void 0 ? _ref : extractIntrinsicsFromTransformation((_message$colorEncoded = message.colorEncodedFrame) === null || _message$colorEncoded === void 0 ? void 0 : _message$colorEncoded.transformation);
|
|
1538
|
+
}
|
|
1539
|
+
function getRGBDIntrinsics(topic, message, fallbackIntrinsics) {
|
|
1540
|
+
const cachedIntrinsics = rgbdIntrinsicsByTopic.get(topic);
|
|
1541
|
+
if (cachedIntrinsics) {
|
|
1542
|
+
return cachedIntrinsics;
|
|
1543
|
+
}
|
|
1544
|
+
const resolvedIntrinsics = resolveRGBDIntrinsicsFromMessage(message);
|
|
1545
|
+
if (resolvedIntrinsics) {
|
|
1546
|
+
rgbdIntrinsicsByTopic.set(topic, resolvedIntrinsics);
|
|
1547
|
+
return resolvedIntrinsics;
|
|
1548
|
+
}
|
|
1549
|
+
return fallbackIntrinsics;
|
|
1451
1550
|
}
|
|
1452
1551
|
async function extractEncodedColorFrame(encodedFrame, topicDecoders, topic) {
|
|
1453
1552
|
const decodeFrame = async () => await new Promise((resolve, reject) => {
|
|
@@ -1557,16 +1656,252 @@ function parseDimensions(message) {
|
|
|
1557
1656
|
}
|
|
1558
1657
|
return obj;
|
|
1559
1658
|
}
|
|
1659
|
+
function emitRGBDDepthPreview(topic, message, maxStereoDepth, callback, onError) {
|
|
1660
|
+
if (!message.depthImgFrame) {
|
|
1661
|
+
return;
|
|
1662
|
+
}
|
|
1663
|
+
const depthFrameForPreview = _objectSpread2(_objectSpread2({}, message.depthImgFrame), {}, {
|
|
1664
|
+
data: message.depthImgFrame.data.slice()
|
|
1665
|
+
});
|
|
1666
|
+
void deserializeDepthFrame({
|
|
1667
|
+
topic,
|
|
1668
|
+
message: depthFrameForPreview,
|
|
1669
|
+
callback,
|
|
1670
|
+
maxStereoDepth: maxStereoDepth / 1000
|
|
1671
|
+
}).catch(onError);
|
|
1672
|
+
}
|
|
1673
|
+
function emitRGBDPointCloud(frame, pointCloudData) {
|
|
1674
|
+
var _frame$timestamp;
|
|
1675
|
+
const foxgloveMessage = {
|
|
1676
|
+
timestamp: (_frame$timestamp = frame.timestamp) !== null && _frame$timestamp !== void 0 ? _frame$timestamp : frame.receiveTime,
|
|
1677
|
+
frame_id: `pointcloud-${frame.topic}-frame`,
|
|
1678
|
+
point_stride: 16,
|
|
1679
|
+
pose: {
|
|
1680
|
+
position: {
|
|
1681
|
+
x: 0,
|
|
1682
|
+
y: 0,
|
|
1683
|
+
z: 0
|
|
1684
|
+
},
|
|
1685
|
+
orientation: {
|
|
1686
|
+
x: 0,
|
|
1687
|
+
y: 0,
|
|
1688
|
+
z: 1,
|
|
1689
|
+
w: 0
|
|
1690
|
+
}
|
|
1691
|
+
},
|
|
1692
|
+
width: frame.depthWidth,
|
|
1693
|
+
height: frame.depthHeight,
|
|
1694
|
+
fields: [{
|
|
1695
|
+
name: "x",
|
|
1696
|
+
offset: 0,
|
|
1697
|
+
type: typescript.NumericType.FLOAT32
|
|
1698
|
+
}, {
|
|
1699
|
+
name: "y",
|
|
1700
|
+
offset: 4,
|
|
1701
|
+
type: typescript.NumericType.FLOAT32
|
|
1702
|
+
}, {
|
|
1703
|
+
name: "z",
|
|
1704
|
+
offset: 8,
|
|
1705
|
+
type: typescript.NumericType.FLOAT32
|
|
1706
|
+
}, {
|
|
1707
|
+
name: "red",
|
|
1708
|
+
offset: 12,
|
|
1709
|
+
type: typescript.NumericType.UINT8
|
|
1710
|
+
}, {
|
|
1711
|
+
name: "green",
|
|
1712
|
+
offset: 13,
|
|
1713
|
+
type: typescript.NumericType.UINT8
|
|
1714
|
+
}, {
|
|
1715
|
+
name: "blue",
|
|
1716
|
+
offset: 14,
|
|
1717
|
+
type: typescript.NumericType.UINT8
|
|
1718
|
+
}, {
|
|
1719
|
+
name: "alpha",
|
|
1720
|
+
offset: 15,
|
|
1721
|
+
type: typescript.NumericType.UINT8
|
|
1722
|
+
}],
|
|
1723
|
+
data: pointCloudData
|
|
1724
|
+
};
|
|
1725
|
+
frame.callback({
|
|
1726
|
+
topic: frame.topic,
|
|
1727
|
+
receiveTime: frame.receiveTime,
|
|
1728
|
+
message: foxgloveMessage,
|
|
1729
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
1730
|
+
schemaName: "foxglove.PointCloud.Colored"
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
function getRGBDBatchSignature(frame) {
|
|
1734
|
+
const intrinsics = frame.rgbdIntrinsics.right;
|
|
1735
|
+
return [frame.depthWidth, frame.depthHeight, frame.colorFrame.width, frame.colorFrame.height, intrinsics.focalLenght.x, intrinsics.focalLenght.y, intrinsics.principalPoint.x, intrinsics.principalPoint.y, frame.maxStereoDepth, frame.hasGPU].join(":");
|
|
1736
|
+
}
|
|
1737
|
+
function clearRGBDBatchFlush(batch) {
|
|
1738
|
+
if (batch.flushTimeoutId != undefined) {
|
|
1739
|
+
clearTimeout(batch.flushTimeoutId);
|
|
1740
|
+
batch.flushTimeoutId = undefined;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
async function processRGBDPointCloudBatchOnWorker(workerSlot, workerIndex, frames) {
|
|
1744
|
+
const firstFrame = frames[0];
|
|
1745
|
+
if (!firstFrame) {
|
|
1746
|
+
workerSlot.activeJobs = Math.max(0, workerSlot.activeJobs - 1);
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
const intrinsics = firstFrame.rgbdIntrinsics.right;
|
|
1750
|
+
let timeoutId;
|
|
1751
|
+
try {
|
|
1752
|
+
const pointClouds = await Promise.race([workerSlot.remote.depthToPointcloudGPU(frames.map(frame => frame.depthFrame), firstFrame.depthWidth, firstFrame.depthHeight, intrinsics.focalLenght.x, intrinsics.focalLenght.y, intrinsics.principalPoint.x, intrinsics.principalPoint.y, frames.map(frame => frame.colorFrame.data), firstFrame.colorFrame.width, firstFrame.colorFrame.height, firstFrame.maxStereoDepth, {
|
|
1753
|
+
hasGPU: firstFrame.hasGPU
|
|
1754
|
+
}), new Promise((_, reject) => {
|
|
1755
|
+
timeoutId = setTimeout(() => {
|
|
1756
|
+
reject(new Error(`RGBD pointcloud worker ${workerIndex} timed out after ${RGBD_POINTCLOUD_WORKER_TIMEOUT_MS}ms for topic ${firstFrame.topic} ` + `(batch=${frames.length}, depth=${firstFrame.depthWidth}x${firstFrame.depthHeight}, color=${firstFrame.colorFrame.width}x${firstFrame.colorFrame.height}, hasGPU=${firstFrame.hasGPU})`));
|
|
1757
|
+
}, RGBD_POINTCLOUD_WORKER_TIMEOUT_MS);
|
|
1758
|
+
})]);
|
|
1759
|
+
if (timeoutId) {
|
|
1760
|
+
clearTimeout(timeoutId);
|
|
1761
|
+
timeoutId = undefined;
|
|
1762
|
+
}
|
|
1763
|
+
if (pointClouds.length !== frames.length) {
|
|
1764
|
+
throw new Error(`RGBD pointcloud worker returned ${pointClouds.length} frames for batch size ${frames.length}`);
|
|
1765
|
+
}
|
|
1766
|
+
for (let index = 0; index < frames.length; index++) {
|
|
1767
|
+
const frame = frames[index];
|
|
1768
|
+
const pointCloud = pointClouds[index];
|
|
1769
|
+
if (!frame || !pointCloud) {
|
|
1770
|
+
continue;
|
|
1771
|
+
}
|
|
1772
|
+
emitRGBDPointCloud(frame, pointCloud);
|
|
1773
|
+
}
|
|
1774
|
+
} catch (error) {
|
|
1775
|
+
if (timeoutId) {
|
|
1776
|
+
clearTimeout(timeoutId);
|
|
1777
|
+
timeoutId = undefined;
|
|
1778
|
+
}
|
|
1779
|
+
if (error instanceof Error && error.message.includes("timed out")) {
|
|
1780
|
+
replaceRGBDPointCloudWorker(workerIndex);
|
|
1781
|
+
console.error(error);
|
|
1782
|
+
}
|
|
1783
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
1784
|
+
for (const frame of frames) {
|
|
1785
|
+
frame.onError(normalizedError);
|
|
1786
|
+
}
|
|
1787
|
+
} finally {
|
|
1788
|
+
workerSlot.activeJobs = Math.max(0, workerSlot.activeJobs - 1);
|
|
1789
|
+
markRGBDPointCloudWorkersActive();
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
async function processRGBDPointCloudOnWorker(workerSlot, workerIndex, frame) {
|
|
1793
|
+
const intrinsics = frame.rgbdIntrinsics.right;
|
|
1794
|
+
let timeoutId;
|
|
1795
|
+
try {
|
|
1796
|
+
const pointClouds = await Promise.race([workerSlot.remote.depthToPointcloudGPU([frame.depthFrame], frame.depthWidth, frame.depthHeight, intrinsics.focalLenght.x, intrinsics.focalLenght.y, intrinsics.principalPoint.x, intrinsics.principalPoint.y, [frame.colorFrame.data], frame.colorFrame.width, frame.colorFrame.height, frame.maxStereoDepth, {
|
|
1797
|
+
hasGPU: frame.hasGPU
|
|
1798
|
+
}), new Promise((_, reject) => {
|
|
1799
|
+
timeoutId = setTimeout(() => {
|
|
1800
|
+
reject(new Error(`RGBD pointcloud worker ${workerIndex} timed out after ${RGBD_POINTCLOUD_WORKER_TIMEOUT_MS}ms for topic ${frame.topic} ` + `(depth=${frame.depthWidth}x${frame.depthHeight}, color=${frame.colorFrame.width}x${frame.colorFrame.height}, hasGPU=${frame.hasGPU})`));
|
|
1801
|
+
}, RGBD_POINTCLOUD_WORKER_TIMEOUT_MS);
|
|
1802
|
+
})]);
|
|
1803
|
+
if (timeoutId) {
|
|
1804
|
+
clearTimeout(timeoutId);
|
|
1805
|
+
timeoutId = undefined;
|
|
1806
|
+
}
|
|
1807
|
+
if (pointClouds.length !== 1 || !pointClouds[0]) {
|
|
1808
|
+
throw new Error(`RGBD pointcloud worker returned ${pointClouds.length} frames for single-frame request`);
|
|
1809
|
+
}
|
|
1810
|
+
emitRGBDPointCloud(frame, pointClouds[0]);
|
|
1811
|
+
} catch (error) {
|
|
1812
|
+
if (timeoutId) {
|
|
1813
|
+
clearTimeout(timeoutId);
|
|
1814
|
+
timeoutId = undefined;
|
|
1815
|
+
}
|
|
1816
|
+
if (error instanceof Error && error.message.includes("timed out")) {
|
|
1817
|
+
replaceRGBDPointCloudWorker(workerIndex);
|
|
1818
|
+
console.error(error);
|
|
1819
|
+
}
|
|
1820
|
+
frame.onError(error instanceof Error ? error : new Error(String(error)));
|
|
1821
|
+
} finally {
|
|
1822
|
+
workerSlot.activeJobs = Math.max(0, workerSlot.activeJobs - 1);
|
|
1823
|
+
markRGBDPointCloudWorkersActive();
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
function flushRGBDPointCloudBatch(topic) {
|
|
1827
|
+
const batch = pendingRGBDBatches.get(topic);
|
|
1828
|
+
if (!batch || batch.frames.length === 0) {
|
|
1829
|
+
pendingRGBDBatches.delete(topic);
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
clearRGBDBatchFlush(batch);
|
|
1833
|
+
pendingRGBDBatches.delete(topic);
|
|
1834
|
+
const reservedWorkerSelection = tryAcquireRGBDPointCloudWorkerSlot();
|
|
1835
|
+
if (!reservedWorkerSelection) {
|
|
1836
|
+
console.warn(`[RGBD] Dropping pointcloud frame for topic ${topic}: all RGBD pointcloud workers are busy.`);
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
void processRGBDPointCloudBatchOnWorker(reservedWorkerSelection.slot, reservedWorkerSelection.index, batch.frames);
|
|
1840
|
+
}
|
|
1841
|
+
function enqueueRGBDPointCloudFrame(frame) {
|
|
1842
|
+
var _pendingRGBDBatches$g;
|
|
1843
|
+
if (!frame.hasGPU) {
|
|
1844
|
+
const reservedWorkerSelection = tryAcquireRGBDPointCloudWorkerSlot();
|
|
1845
|
+
if (!reservedWorkerSelection) {
|
|
1846
|
+
console.warn(`[RGBD] Dropping pointcloud frame for topic ${frame.topic}: all RGBD pointcloud workers are busy.`);
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
globalRenderMetricsManager.ensureTopic(constructKeyForTopicRenderMetrics("renderPointCloudFrame", "Point Cloud"));
|
|
1850
|
+
globalInputEventMetricsManager.registerEvent(constructKeyForTopicRenderMetrics("incomingPointCloudFrame", "Point Cloud"));
|
|
1851
|
+
globalDecodeMetricsManager.registerEvent("Point Cloud");
|
|
1852
|
+
void processRGBDPointCloudOnWorker(reservedWorkerSelection.slot, reservedWorkerSelection.index, frame);
|
|
1853
|
+
return;
|
|
1854
|
+
}
|
|
1855
|
+
const existingBatch = pendingRGBDBatches.get(frame.topic);
|
|
1856
|
+
if (existingBatch && existingBatch.frames.length > 0 && getRGBDBatchSignature(existingBatch.frames[0]) !== getRGBDBatchSignature(frame)) {
|
|
1857
|
+
flushRGBDPointCloudBatch(frame.topic);
|
|
1858
|
+
}
|
|
1859
|
+
const batch = (_pendingRGBDBatches$g = pendingRGBDBatches.get(frame.topic)) !== null && _pendingRGBDBatches$g !== void 0 ? _pendingRGBDBatches$g : {
|
|
1860
|
+
frames: []
|
|
1861
|
+
};
|
|
1862
|
+
batch.frames.push(frame);
|
|
1863
|
+
pendingRGBDBatches.set(frame.topic, batch);
|
|
1864
|
+
if (batch.frames.length >= RGBD_GPU_BATCH_SIZE) {
|
|
1865
|
+
flushRGBDPointCloudBatch(frame.topic);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
clearRGBDBatchFlush(batch);
|
|
1869
|
+
batch.flushTimeoutId = setTimeout(() => {
|
|
1870
|
+
flushRGBDPointCloudBatch(frame.topic);
|
|
1871
|
+
}, RGBD_GPU_BATCH_FLUSH_DELAY_MS);
|
|
1872
|
+
}
|
|
1560
1873
|
async function deserializeRGBDFrameToPointCloud({
|
|
1561
1874
|
topic,
|
|
1562
1875
|
topicDecoders,
|
|
1563
1876
|
cameraIntrinsics,
|
|
1564
1877
|
maxStereoDepth,
|
|
1565
1878
|
message,
|
|
1566
|
-
callback
|
|
1879
|
+
callback,
|
|
1880
|
+
onError
|
|
1881
|
+
}) {
|
|
1882
|
+
markRGBDPointCloudWorkersActive();
|
|
1883
|
+
emitRGBDDepthPreview(topic, message, maxStereoDepth, callback, onError);
|
|
1884
|
+
setTimeout(() => {
|
|
1885
|
+
void processScheduledRGBDPointCloud({
|
|
1886
|
+
topic,
|
|
1887
|
+
topicDecoders,
|
|
1888
|
+
cameraIntrinsics,
|
|
1889
|
+
maxStereoDepth,
|
|
1890
|
+
message,
|
|
1891
|
+
callback,
|
|
1892
|
+
onError
|
|
1893
|
+
});
|
|
1894
|
+
}, RGBD_POINTCLOUD_SCHEDULE_DELAY_MS);
|
|
1895
|
+
}
|
|
1896
|
+
async function processScheduledRGBDPointCloud({
|
|
1897
|
+
topic,
|
|
1898
|
+
topicDecoders,
|
|
1899
|
+
cameraIntrinsics,
|
|
1900
|
+
maxStereoDepth,
|
|
1901
|
+
message,
|
|
1902
|
+
callback,
|
|
1903
|
+
onError
|
|
1567
1904
|
}) {
|
|
1568
|
-
const workerSlot = getRGBDPointCloudWorkerSlot();
|
|
1569
|
-
workerSlot.activeJobs += 1;
|
|
1570
1905
|
const {
|
|
1571
1906
|
receiveTime
|
|
1572
1907
|
} = parseMessage(message);
|
|
@@ -1574,83 +1909,29 @@ async function deserializeRGBDFrameToPointCloud({
|
|
|
1574
1909
|
depthWidth,
|
|
1575
1910
|
depthHeight
|
|
1576
1911
|
} = parseDimensions(message);
|
|
1577
|
-
const rgbdIntrinsics =
|
|
1578
|
-
const hasGPU =
|
|
1579
|
-
const colorFrame = await extractColorFrame(message.colorEncodedFrame, message.colorImgFrame, topicDecoders, topic);
|
|
1580
|
-
const uint8DepthFrames = extractDepthFrame(message.depthEncodedFrame, message.depthImgFrame);
|
|
1581
|
-
const depthFrames = uint8ArrayToUint16Array(uint8DepthFrames);
|
|
1912
|
+
const rgbdIntrinsics = getRGBDIntrinsics(topic, message, cameraIntrinsics);
|
|
1913
|
+
const hasGPU = getRGBDGPUSupport();
|
|
1582
1914
|
try {
|
|
1583
|
-
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
const foxgloveMessage = {
|
|
1588
|
-
timestamp: (_message$tsDevice = message.tsDevice) !== null && _message$tsDevice !== void 0 ? _message$tsDevice : receiveTime,
|
|
1589
|
-
frame_id: `pointcloud-${topic}-frame`,
|
|
1590
|
-
point_stride: 16,
|
|
1591
|
-
pose: {
|
|
1592
|
-
position: {
|
|
1593
|
-
x: 0,
|
|
1594
|
-
y: 0,
|
|
1595
|
-
z: 0
|
|
1596
|
-
},
|
|
1597
|
-
orientation: {
|
|
1598
|
-
x: 0,
|
|
1599
|
-
y: 0,
|
|
1600
|
-
z: 1,
|
|
1601
|
-
w: 0
|
|
1602
|
-
}
|
|
1603
|
-
},
|
|
1604
|
-
width: depthWidth,
|
|
1605
|
-
height: depthHeight,
|
|
1606
|
-
fields: [{
|
|
1607
|
-
name: "x",
|
|
1608
|
-
offset: 0,
|
|
1609
|
-
type: typescript.NumericType.FLOAT32
|
|
1610
|
-
}, {
|
|
1611
|
-
name: "y",
|
|
1612
|
-
offset: 4,
|
|
1613
|
-
type: typescript.NumericType.FLOAT32
|
|
1614
|
-
}, {
|
|
1615
|
-
name: "z",
|
|
1616
|
-
offset: 8,
|
|
1617
|
-
type: typescript.NumericType.FLOAT32
|
|
1618
|
-
}, {
|
|
1619
|
-
name: "red",
|
|
1620
|
-
offset: 12,
|
|
1621
|
-
type: typescript.NumericType.UINT8
|
|
1622
|
-
}, {
|
|
1623
|
-
name: "green",
|
|
1624
|
-
offset: 13,
|
|
1625
|
-
type: typescript.NumericType.UINT8
|
|
1626
|
-
}, {
|
|
1627
|
-
name: "blue",
|
|
1628
|
-
offset: 14,
|
|
1629
|
-
type: typescript.NumericType.UINT8
|
|
1630
|
-
}, {
|
|
1631
|
-
name: "alpha",
|
|
1632
|
-
offset: 15,
|
|
1633
|
-
type: typescript.NumericType.UINT8
|
|
1634
|
-
}],
|
|
1635
|
-
data: pointCloud[0]
|
|
1636
|
-
};
|
|
1637
|
-
callback({
|
|
1915
|
+
const colorFrame = await extractColorFrame(message.colorEncodedFrame, message.colorImgFrame, topicDecoders, topic);
|
|
1916
|
+
const uint8DepthFrames = extractDepthFrame(message.depthEncodedFrame, message.depthImgFrame);
|
|
1917
|
+
const depthFrame = uint8ArrayToUint16Array(uint8DepthFrames);
|
|
1918
|
+
const pendingFrame = {
|
|
1638
1919
|
topic,
|
|
1639
1920
|
receiveTime,
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1921
|
+
timestamp: message.tsDevice,
|
|
1922
|
+
depthWidth,
|
|
1923
|
+
depthHeight,
|
|
1924
|
+
rgbdIntrinsics,
|
|
1925
|
+
colorFrame,
|
|
1926
|
+
depthFrame,
|
|
1927
|
+
maxStereoDepth,
|
|
1928
|
+
hasGPU,
|
|
1929
|
+
callback,
|
|
1930
|
+
onError
|
|
1931
|
+
};
|
|
1932
|
+
enqueueRGBDPointCloudFrame(pendingFrame);
|
|
1933
|
+
} catch (error) {
|
|
1934
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
1654
1935
|
}
|
|
1655
1936
|
}
|
|
1656
1937
|
|