@luxonis/depthai-viewer-common 3.9.7 → 4.0.0

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 (154) hide show
  1. package/THIRD_PARTY_NOTICES.md +36 -304
  2. package/benchmark-cli.mjs +166 -11
  3. package/benchmark-lib.sh +40 -5
  4. package/benchmark-root.sh +79 -13
  5. package/benchmark.sh +112 -5
  6. package/dist/components/Streams.d.ts +6 -0
  7. package/dist/components/Streams.d.ts.map +1 -1
  8. package/dist/components/Streams.js +12 -4
  9. package/dist/components/Streams.js.map +1 -1
  10. package/dist/hooks/benchmark-automation.d.ts.map +1 -1
  11. package/dist/hooks/benchmark-automation.js +288 -63
  12. package/dist/hooks/benchmark-automation.js.map +1 -1
  13. package/dist/index.css +7 -0
  14. package/dist/utils/vite-dev-fix.d.ts.map +1 -1
  15. package/dist/utils/vite-dev-fix.js +0 -15
  16. package/dist/utils/vite-dev-fix.js.map +1 -1
  17. package/dist/visualizer/components/Panel.d.ts.map +1 -1
  18. package/dist/visualizer/components/Panel.js +6 -3
  19. package/dist/visualizer/components/Panel.js.map +1 -1
  20. package/dist/visualizer/components/shared-interval.d.ts +1 -1
  21. package/dist/visualizer/components/shared-interval.d.ts.map +1 -1
  22. package/dist/visualizer/components/shared-interval.js +6 -2
  23. package/dist/visualizer/components/shared-interval.js.map +1 -1
  24. package/dist/visualizer/connection/communicator.d.ts +1 -0
  25. package/dist/visualizer/connection/communicator.d.ts.map +1 -1
  26. package/dist/visualizer/connection/communicator.js.map +1 -1
  27. package/dist/visualizer/connection/connection.d.ts.map +1 -1
  28. package/dist/visualizer/connection/connection.js +8 -7
  29. package/dist/visualizer/connection/connection.js.map +1 -1
  30. package/dist/visualizer/connection/foxglove-connection.d.ts +4 -2
  31. package/dist/visualizer/connection/foxglove-connection.d.ts.map +1 -1
  32. package/dist/visualizer/connection/foxglove-connection.js +88 -40
  33. package/dist/visualizer/connection/foxglove-connection.js.map +1 -1
  34. package/dist/visualizer/context/MessagePipelineProvider.d.ts +1 -1
  35. package/dist/visualizer/context/MessagePipelineProvider.d.ts.map +1 -1
  36. package/dist/visualizer/context/MessagePipelineProvider.js +24 -6
  37. package/dist/visualizer/context/MessagePipelineProvider.js.map +1 -1
  38. package/dist/visualizer/context/VisualizerContext.d.ts.map +1 -1
  39. package/dist/visualizer/context/VisualizerContext.js +1 -32
  40. package/dist/visualizer/context/VisualizerContext.js.map +1 -1
  41. package/dist/visualizer/index.d.ts +1 -0
  42. package/dist/visualizer/index.d.ts.map +1 -1
  43. package/dist/visualizer/index.js +1 -0
  44. package/dist/visualizer/index.js.map +1 -1
  45. package/dist/visualizer/messaging/browser-decoder-fixtures.d.ts.map +1 -1
  46. package/dist/visualizer/messaging/browser-decoder-fixtures.js +187 -24
  47. package/dist/visualizer/messaging/browser-decoder-fixtures.js.map +1 -1
  48. package/dist/visualizer/messaging/decode-core.d.ts +9 -1
  49. package/dist/visualizer/messaging/decode-core.d.ts.map +1 -1
  50. package/dist/visualizer/messaging/decode-core.js +26 -16
  51. package/dist/visualizer/messaging/decode-core.js.map +1 -1
  52. package/dist/visualizer/messaging/decoder-fixtures.d.ts.map +1 -1
  53. package/dist/visualizer/messaging/decoder-fixtures.js +128 -1
  54. package/dist/visualizer/messaging/decoder-fixtures.js.map +1 -1
  55. package/dist/visualizer/messaging/decoder-harness.d.ts +2 -1
  56. package/dist/visualizer/messaging/decoder-harness.d.ts.map +1 -1
  57. package/dist/visualizer/messaging/decoder-harness.js.map +1 -1
  58. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.d.ts +6 -1
  59. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.d.ts.map +1 -1
  60. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js +5 -1
  61. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js.map +1 -1
  62. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.d.ts +10 -14
  63. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.d.ts.map +1 -1
  64. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.js +56 -288
  65. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.js.map +1 -1
  66. package/dist/visualizer/messaging/deserialization/pointcloud/utils.d.ts.map +1 -1
  67. package/dist/visualizer/messaging/deserialization/pointcloud/utils.js +2 -7
  68. package/dist/visualizer/messaging/deserialization/pointcloud/utils.js.map +1 -1
  69. package/dist/visualizer/messaging/deserialization/video/depth.d.ts +2 -1
  70. package/dist/visualizer/messaging/deserialization/video/depth.d.ts.map +1 -1
  71. package/dist/visualizer/messaging/deserialization/video/depth.js +9 -65
  72. package/dist/visualizer/messaging/deserialization/video/depth.js.map +1 -1
  73. package/dist/visualizer/messaging/deserialization/video/h264.d.ts +3 -3
  74. package/dist/visualizer/messaging/deserialization/video/h264.d.ts.map +1 -1
  75. package/dist/visualizer/messaging/deserialization/video/h264.js +80 -25
  76. package/dist/visualizer/messaging/deserialization/video/h264.js.map +1 -1
  77. package/dist/visualizer/messaging/deserialization/video/h265.d.ts +1 -1
  78. package/dist/visualizer/messaging/deserialization/video/h265.d.ts.map +1 -1
  79. package/dist/visualizer/messaging/deserialization/video/h265.js +62 -22
  80. package/dist/visualizer/messaging/deserialization/video/h265.js.map +1 -1
  81. package/dist/visualizer/messaging/deserialization/video/mjpeg.d.ts +1 -0
  82. package/dist/visualizer/messaging/deserialization/video/mjpeg.d.ts.map +1 -1
  83. package/dist/visualizer/messaging/deserialization/video/mjpeg.js +14 -2
  84. package/dist/visualizer/messaging/deserialization/video/mjpeg.js.map +1 -1
  85. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.d.ts +3 -1
  86. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.d.ts.map +1 -1
  87. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.js +152 -250
  88. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.js.map +1 -1
  89. package/dist/visualizer/messaging/deserialization.worker.d.ts +5 -3
  90. package/dist/visualizer/messaging/deserialization.worker.d.ts.map +1 -1
  91. package/dist/visualizer/messaging/deserialization.worker.js +16 -2
  92. package/dist/visualizer/messaging/deserialization.worker.js.map +1 -1
  93. package/dist/visualizer/messaging/message-event.d.ts +3 -0
  94. package/dist/visualizer/messaging/message-event.d.ts.map +1 -1
  95. package/dist/visualizer/messaging/message-event.js +18 -4
  96. package/dist/visualizer/messaging/message-event.js.map +1 -1
  97. package/dist/visualizer/messaging/message-handler.d.ts +3 -1
  98. package/dist/visualizer/messaging/message-handler.d.ts.map +1 -1
  99. package/dist/visualizer/messaging/message-handler.js +120 -49
  100. package/dist/visualizer/messaging/message-handler.js.map +1 -1
  101. package/dist/visualizer/output.css +7 -0
  102. package/dist/visualizer/panels/PointCloudPanel.d.ts.map +1 -1
  103. package/dist/visualizer/panels/PointCloudPanel.js +2 -0
  104. package/dist/visualizer/panels/PointCloudPanel.js.map +1 -1
  105. package/dist/visualizer/panels/image/ImageCanvasRenderer.d.ts.map +1 -1
  106. package/dist/visualizer/panels/image/ImageCanvasRenderer.js +246 -69
  107. package/dist/visualizer/panels/image/ImageCanvasRenderer.js.map +1 -1
  108. package/dist/visualizer/panels/image/annotation-overlay.d.ts.map +1 -1
  109. package/dist/visualizer/panels/image/annotation-overlay.js +16 -2
  110. package/dist/visualizer/panels/image/annotation-overlay.js.map +1 -1
  111. package/dist/visualizer/panels/image/raw-image-decoder.d.ts.map +1 -1
  112. package/dist/visualizer/panels/image/raw-image-decoder.js +1 -0
  113. package/dist/visualizer/panels/image/raw-image-decoder.js.map +1 -1
  114. package/dist/visualizer/panels/image/webgl-image-renderer.d.ts +11 -2
  115. package/dist/visualizer/panels/image/webgl-image-renderer.d.ts.map +1 -1
  116. package/dist/visualizer/panels/image/webgl-image-renderer.js +236 -41
  117. package/dist/visualizer/panels/image/webgl-image-renderer.js.map +1 -1
  118. package/dist/visualizer/panels/image/webgl-segmentation-mask-renderer.d.ts +16 -0
  119. package/dist/visualizer/panels/image/webgl-segmentation-mask-renderer.d.ts.map +1 -0
  120. package/dist/visualizer/panels/image/webgl-segmentation-mask-renderer.js +184 -0
  121. package/dist/visualizer/panels/image/webgl-segmentation-mask-renderer.js.map +1 -0
  122. package/dist/visualizer/panels/image/worker-image-decoder.d.ts.map +1 -1
  123. package/dist/visualizer/panels/image/worker-image-decoder.js +8 -3
  124. package/dist/visualizer/panels/image/worker-image-decoder.js.map +1 -1
  125. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.d.ts.map +1 -1
  126. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.js +256 -73
  127. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.js.map +1 -1
  128. package/dist/visualizer/panels/pointcloud/point-cloud-materials.d.ts +5 -0
  129. package/dist/visualizer/panels/pointcloud/point-cloud-materials.d.ts.map +1 -0
  130. package/dist/visualizer/panels/pointcloud/point-cloud-materials.js +123 -0
  131. package/dist/visualizer/panels/pointcloud/point-cloud-materials.js.map +1 -0
  132. package/dist/visualizer/protobuf.generated/NNData.d.ts +92 -0
  133. package/dist/visualizer/protobuf.generated/NNData.d.ts.map +1 -0
  134. package/dist/visualizer/protobuf.generated/NNData.js +620 -0
  135. package/dist/visualizer/protobuf.generated/NNData.js.map +1 -0
  136. package/dist/visualizer/utils/benchmark-metrics.d.ts +27 -0
  137. package/dist/visualizer/utils/benchmark-metrics.d.ts.map +1 -0
  138. package/dist/visualizer/utils/benchmark-metrics.js +139 -0
  139. package/dist/visualizer/utils/benchmark-metrics.js.map +1 -0
  140. package/dist/visualizer/utils/comlink-wrap.d.ts.map +1 -1
  141. package/dist/visualizer/utils/comlink-wrap.js +5 -0
  142. package/dist/visualizer/utils/comlink-wrap.js.map +1 -1
  143. package/dist/visualizer/utils/poitcloud-sync.d.ts.map +1 -1
  144. package/dist/visualizer/utils/poitcloud-sync.js +5 -2
  145. package/dist/visualizer/utils/poitcloud-sync.js.map +1 -1
  146. package/package.json +3 -4
  147. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.d.ts +0 -2
  148. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.d.ts.map +0 -1
  149. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.js +0 -45
  150. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.js.map +0 -1
  151. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.d.ts +0 -5
  152. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.d.ts.map +0 -1
  153. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.js +0 -124
  154. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PointCloudPanel.js","sourceRoot":"","sources":["../../../src/visualizer/panels/PointCloudPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PointCloudPanel.js","sourceRoot":"","sources":["../../../src/visualizer/panels/PointCloudPanel.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageCanvasRenderer.d.ts","sourceRoot":"","sources":["../../../../src/visualizer/panels/image/ImageCanvasRenderer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAM1D,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,8BAA8B,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5C,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,KAAK,CAAC,UAAU,EACvB,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,0BAA0B,CAAC,EAAE,CAC3B,WAAW,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EACrC,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACrD,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AA8CF,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,8BAA8B,EAC9B,aAAa,EACb,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,WAAmB,GACpB,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,CAuyB/C"}
1
+ {"version":3,"file":"ImageCanvasRenderer.d.ts","sourceRoot":"","sources":["../../../../src/visualizer/panels/image/ImageCanvasRenderer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO1D,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,8BAA8B,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5C,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,KAAK,CAAC,UAAU,EACvB,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,0BAA0B,CAAC,EAAE,CAC3B,WAAW,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EACrC,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACrD,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAoFF,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,8BAA8B,EAC9B,aAAa,EACb,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,WAAmB,GACpB,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,CAo9B/C"}
@@ -6,10 +6,12 @@ import React from "react";
6
6
  import { useDetections } from "../../components/Panel.js";
7
7
  import { recordRenderFrame } from "../../messaging/stream-diagnostics.js";
8
8
  import { useMessageSubscription } from "../../messaging/utils.js";
9
+ import { recordBenchmarkRendered } from "../../utils/benchmark-metrics.js";
9
10
  import { readCanvasColor } from "../../utils/use-theme-mode.js";
10
11
  import { drawImageAnnotations } from "./annotation-overlay.js";
11
12
  import { drawSegmentationMasks } from "./segmentation-mask-overlay.js";
12
13
  import { WebGlImageRenderer } from "./webgl-image-renderer.js";
14
+ import { WebGlSegmentationMaskRenderer } from "./webgl-segmentation-mask-renderer.js";
13
15
  import { WorkerImageDecoder } from "./worker-image-decoder.js";
14
16
  const MIN_ZOOM = 1;
15
17
  const MAX_ZOOM = 8;
@@ -17,14 +19,39 @@ const WHEEL_ZOOM_STEP = 0.0015;
17
19
  const RESET_ZOOM_EVENT_NAME = "visualizer:image-reset-zoom";
18
20
  const ZOOM_STATE_EVENT_NAME = "visualizer:image-zoom-state";
19
21
  const ANNOTATION_STALE_TIMEOUT_MS = 500;
22
+ const MAX_IMAGE_DEVICE_PIXEL_RATIO = 1.5;
23
+ const CONSTRAINED_IMAGE_DEVICE_PIXEL_RATIO = 1;
24
+ function getImageCanvasPixelRatio() {
25
+ const devicePixelRatio = window.devicePixelRatio || 1;
26
+ const deviceMemory = navigator.deviceMemory;
27
+ const isConstrainedDevice = (deviceMemory != undefined && deviceMemory <= 4) || navigator.hardwareConcurrency <= 4;
28
+ const maximumPixelRatio = isConstrainedDevice
29
+ ? CONSTRAINED_IMAGE_DEVICE_PIXEL_RATIO
30
+ : MAX_IMAGE_DEVICE_PIXEL_RATIO;
31
+ return Math.max(1, Math.min(devicePixelRatio, maximumPixelRatio));
32
+ }
33
+ function releaseCanvasBackingStore(canvas) {
34
+ if (canvas.width !== 1 || canvas.height !== 1) {
35
+ canvas.width = 1;
36
+ canvas.height = 1;
37
+ }
38
+ }
39
+ function releaseOffscreenCanvasBackingStore(canvas) {
40
+ if (canvas && (canvas.width !== 1 || canvas.height !== 1)) {
41
+ canvas.width = 1;
42
+ canvas.height = 1;
43
+ }
44
+ }
20
45
  export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTopics, frameRenderedEvent, annotationReceivedEventHandler, handleOnClick, handleCursorPositionUpdate, registerRendered, unregisterRendered, customOverlay, disableZoom = false, }) {
21
46
  const canvas2dRef = React.useRef(null);
22
47
  const webGlCanvasRef = React.useRef(null);
23
48
  const overlayCanvasRef = React.useRef(null);
49
+ const segmentationCanvasRef = React.useRef(null);
24
50
  const containerRef = React.useRef(null);
25
51
  const offscreenCanvasRef = React.useRef(null);
26
52
  const decoderRef = React.useRef(undefined);
27
53
  const webGlRendererRef = React.useRef(undefined);
54
+ const segmentationRendererRef = React.useRef(undefined);
28
55
  const decodedRenderableRef = React.useRef(undefined);
29
56
  const activeBitmapRef = React.useRef(undefined);
30
57
  const viewSizeRef = React.useRef({ width: 0, height: 0 });
@@ -32,7 +59,12 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
32
59
  const segmentationMasksByTopicRef = React.useRef(new Map());
33
60
  const visibleAnnotationsRef = React.useRef([]);
34
61
  const visibleSegmentationMasksRef = React.useRef([]);
62
+ const baseDirtyRef = React.useRef(true);
63
+ const overlayDirtyRef = React.useRef(true);
64
+ const nextOverlayExpiryRef = React.useRef(Number.POSITIVE_INFINITY);
35
65
  const imageRevisionRef = React.useRef(0);
66
+ const lastDrawnImageRevisionRef = React.useRef(-1);
67
+ const lastRenderSourceRef = React.useRef("image-render:image-data");
36
68
  const decodeRequestIdRef = React.useRef(0);
37
69
  const decodeInFlightRef = React.useRef(false);
38
70
  const decodePumpRequestIdRef = React.useRef(undefined);
@@ -77,6 +109,9 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
77
109
  if (rendererModeRef.current === nextMode) {
78
110
  return;
79
111
  }
112
+ if (nextMode === "canvas2d") {
113
+ webGlRendererRef.current?.releaseFrameResources();
114
+ }
80
115
  rendererModeRef.current = nextMode;
81
116
  setRendererMode(nextMode);
82
117
  }, []);
@@ -107,10 +142,28 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
107
142
  }
108
143
  return decoder;
109
144
  }, []);
145
+ const ensureSegmentationRenderer = React.useCallback(() => {
146
+ if (segmentationRendererRef.current === null) {
147
+ return undefined;
148
+ }
149
+ if (segmentationRendererRef.current) {
150
+ return segmentationRendererRef.current;
151
+ }
152
+ const canvas = segmentationCanvasRef.current;
153
+ if (!canvas) {
154
+ return undefined;
155
+ }
156
+ segmentationRendererRef.current = WebGlSegmentationMaskRenderer.create(canvas) ?? null;
157
+ return segmentationRendererRef.current ?? undefined;
158
+ }, []);
110
159
  const releaseDecodedRenderable = React.useCallback((renderable) => {
111
160
  if (!renderable || renderable.kind === "raw-image") {
112
161
  return;
113
162
  }
163
+ if (renderable.kind === "video-frame") {
164
+ renderable.frame.close();
165
+ return;
166
+ }
114
167
  if (renderable.kind === "bitmap") {
115
168
  renderable.bitmap.close();
116
169
  if (activeBitmapRef.current === renderable.bitmap) {
@@ -126,111 +179,183 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
126
179
  const canvas2d = canvas2dRef.current;
127
180
  const webGlCanvas = webGlCanvasRef.current;
128
181
  const overlayCanvas = overlayCanvasRef.current;
182
+ const segmentationCanvas = segmentationCanvasRef.current;
129
183
  const decodedRenderable = decodedRenderableRef.current;
130
- if (!canvas2d || !webGlCanvas || !overlayCanvas) {
184
+ if (!canvas2d || !webGlCanvas || !overlayCanvas || !segmentationCanvas) {
131
185
  return;
132
186
  }
133
187
  const drawStart = performance.now();
134
- const dpr = window.devicePixelRatio || 1;
188
+ if (!decodedRenderable) {
189
+ baseDirtyRef.current = true;
190
+ lastDrawnImageRevisionRef.current = -1;
191
+ releaseCanvasBackingStore(canvas2d);
192
+ releaseCanvasBackingStore(webGlCanvas);
193
+ releaseCanvasBackingStore(overlayCanvas);
194
+ releaseCanvasBackingStore(segmentationCanvas);
195
+ releaseOffscreenCanvasBackingStore(offscreenCanvasRef.current);
196
+ return;
197
+ }
198
+ const dpr = getImageCanvasPixelRatio();
135
199
  const width = Math.max(Math.floor(viewSizeRef.current.width * dpr), 1);
136
200
  const height = Math.max(Math.floor(viewSizeRef.current.height * dpr), 1);
137
201
  if (overlayCanvas.width !== width || overlayCanvas.height !== height) {
138
202
  overlayCanvas.width = width;
139
203
  overlayCanvas.height = height;
204
+ baseDirtyRef.current = true;
205
+ overlayDirtyRef.current = true;
140
206
  }
141
207
  const overlayCtx = overlayCanvas.getContext("2d");
142
208
  if (!overlayCtx) {
143
209
  return;
144
210
  }
145
- overlayCtx.setTransform(1, 0, 0, 1, 0, 0);
146
- overlayCtx.clearRect(0, 0, width, height);
147
- if (!decodedRenderable) {
148
- return;
149
- }
150
211
  const baseRect = calculateDrawRect(decodedRenderable.width, decodedRenderable.height, viewSizeRef.current.width, viewSizeRef.current.height);
151
212
  const rect = applyViewTransform(baseRect, viewTransformRef.current);
152
213
  const scaledRect = scaleDrawRect(rect, dpr);
153
- let renderSource = "image-render:image-data";
154
- if (decodedRenderable.kind === "raw-image") {
155
- if (webGlCanvas.width !== width || webGlCanvas.height !== height) {
156
- webGlCanvas.width = width;
157
- webGlCanvas.height = height;
158
- }
159
- const webGlRenderer = ensureWebGlRenderer();
160
- if (webGlRenderer?.draw(decodedRenderable.image, width, height, scaledRect)) {
161
- renderSource = "image-render:webgl";
162
- }
163
- }
164
- if (renderSource !== "image-render:webgl") {
165
- if (canvas2d.width !== width || canvas2d.height !== height) {
166
- canvas2d.width = width;
167
- canvas2d.height = height;
168
- }
169
- const imageCtx = canvas2d.getContext("2d");
170
- if (!imageCtx) {
171
- return;
172
- }
173
- imageCtx.setTransform(1, 0, 0, 1, 0, 0);
174
- imageCtx.clearRect(0, 0, width, height);
175
- imageCtx.imageSmoothingEnabled = false;
176
- imageCtx.fillStyle = readCanvasColor();
177
- imageCtx.fillRect(0, 0, width, height);
178
- if (decodedRenderable.kind === "bitmap") {
179
- imageCtx.drawImage(decodedRenderable.bitmap, scaledRect.x, scaledRect.y, scaledRect.width, scaledRect.height);
180
- renderSource = "image-render:bitmap";
214
+ const imageRevision = imageRevisionRef.current;
215
+ const shouldDrawBase = baseDirtyRef.current || lastDrawnImageRevisionRef.current !== imageRevision;
216
+ let renderSource = lastRenderSourceRef.current;
217
+ if (shouldDrawBase) {
218
+ renderSource = "image-render:image-data";
219
+ if (decodedRenderable.kind === "raw-image") {
220
+ if (webGlCanvas.width !== width || webGlCanvas.height !== height) {
221
+ webGlCanvas.width = width;
222
+ webGlCanvas.height = height;
223
+ }
224
+ const webGlRenderer = ensureWebGlRenderer();
225
+ if (webGlRenderer?.draw(decodedRenderable.image, width, height, scaledRect)) {
226
+ renderSource = "image-render:webgl";
227
+ }
181
228
  }
182
- else if (decodedRenderable.kind === "image-data") {
183
- const offscreenCanvas = getOffscreenCanvas(offscreenCanvasRef, decodedRenderable.imageData.width, decodedRenderable.imageData.height);
184
- const offscreenCtx = offscreenCanvas.getContext("2d");
185
- if (!offscreenCtx) {
229
+ if (renderSource !== "image-render:webgl") {
230
+ if (canvas2d.width !== width || canvas2d.height !== height) {
231
+ canvas2d.width = width;
232
+ canvas2d.height = height;
233
+ }
234
+ const imageCtx = canvas2d.getContext("2d");
235
+ if (!imageCtx) {
186
236
  return;
187
237
  }
188
- offscreenCtx.putImageData(decodedRenderable.imageData, 0, 0);
189
- imageCtx.drawImage(offscreenCanvas, scaledRect.x, scaledRect.y, scaledRect.width, scaledRect.height);
238
+ imageCtx.setTransform(1, 0, 0, 1, 0, 0);
239
+ imageCtx.clearRect(0, 0, width, height);
240
+ imageCtx.imageSmoothingEnabled = false;
241
+ imageCtx.fillStyle = readCanvasColor();
242
+ imageCtx.fillRect(0, 0, width, height);
243
+ if (decodedRenderable.kind === "bitmap") {
244
+ imageCtx.drawImage(decodedRenderable.bitmap, scaledRect.x, scaledRect.y, scaledRect.width, scaledRect.height);
245
+ renderSource = "image-render:bitmap";
246
+ }
247
+ else if (decodedRenderable.kind === "video-frame") {
248
+ imageCtx.drawImage(decodedRenderable.frame, scaledRect.x, scaledRect.y, scaledRect.width, scaledRect.height);
249
+ renderSource = "image-render:video-frame";
250
+ }
251
+ else if (decodedRenderable.kind === "image-data") {
252
+ const offscreenCanvas = getOffscreenCanvas(offscreenCanvasRef, decodedRenderable.imageData.width, decodedRenderable.imageData.height);
253
+ const offscreenCtx = offscreenCanvas.getContext("2d");
254
+ if (!offscreenCtx) {
255
+ return;
256
+ }
257
+ offscreenCtx.putImageData(decodedRenderable.imageData, 0, 0);
258
+ imageCtx.drawImage(offscreenCanvas, scaledRect.x, scaledRect.y, scaledRect.width, scaledRect.height);
259
+ }
260
+ else {
261
+ renderSource = "image-render:webgl-fallback";
262
+ }
190
263
  }
191
- else {
192
- renderSource = "image-render:webgl-fallback";
264
+ const nextRendererMode = renderSource === "image-render:webgl" ? "webgl" : "canvas2d";
265
+ setRendererModeIfChanged(nextRendererMode);
266
+ releaseCanvasBackingStore(nextRendererMode === "webgl" ? canvas2d : webGlCanvas);
267
+ if (decodedRenderable.kind !== "image-data") {
268
+ releaseOffscreenCanvasBackingStore(offscreenCanvasRef.current);
193
269
  }
270
+ baseDirtyRef.current = false;
271
+ lastDrawnImageRevisionRef.current = imageRevision;
272
+ lastRenderSourceRef.current = renderSource;
194
273
  }
195
274
  const now = performance.now();
196
- const enabledTopics = visibleAnnotationsRef.current;
197
- enabledTopics.length = 0;
198
- const enabledSegmentationMasks = visibleSegmentationMasksRef.current;
199
- enabledSegmentationMasks.length = 0;
200
- for (const annotationTopic of allAnnotationTopics) {
201
- const isEnabled = isAnnotationTopicEnabled(detectionsRef.current, annotationTopic);
202
- const annotationEntry = annotationsByTopicRef.current.get(annotationTopic);
203
- if (annotationEntry) {
204
- if (now - annotationEntry.receivedAt > ANNOTATION_STALE_TIMEOUT_MS) {
205
- annotationsByTopicRef.current.delete(annotationTopic);
275
+ if (now >= nextOverlayExpiryRef.current) {
276
+ overlayDirtyRef.current = true;
277
+ }
278
+ if (overlayDirtyRef.current) {
279
+ overlayCtx.setTransform(1, 0, 0, 1, 0, 0);
280
+ overlayCtx.clearRect(0, 0, width, height);
281
+ const enabledTopics = visibleAnnotationsRef.current;
282
+ enabledTopics.length = 0;
283
+ const enabledSegmentationMasks = visibleSegmentationMasksRef.current;
284
+ enabledSegmentationMasks.length = 0;
285
+ let nextExpiry = Number.POSITIVE_INFINITY;
286
+ for (const annotationTopic of allAnnotationTopics) {
287
+ const isEnabled = isAnnotationTopicEnabled(detectionsRef.current, annotationTopic);
288
+ const annotationEntry = annotationsByTopicRef.current.get(annotationTopic);
289
+ if (annotationEntry) {
290
+ const expiresAt = annotationEntry.receivedAt + ANNOTATION_STALE_TIMEOUT_MS;
291
+ if (now >= expiresAt) {
292
+ annotationsByTopicRef.current.delete(annotationTopic);
293
+ }
294
+ else {
295
+ nextExpiry = Math.min(nextExpiry, expiresAt);
296
+ if (isEnabled) {
297
+ enabledTopics.push(annotationEntry.annotation);
298
+ }
299
+ }
206
300
  }
207
- else if (isEnabled) {
208
- enabledTopics.push(annotationEntry.annotation);
301
+ const segmentationMaskEntry = segmentationMasksByTopicRef.current.get(annotationTopic);
302
+ if (segmentationMaskEntry) {
303
+ const expiresAt = segmentationMaskEntry.receivedAt + ANNOTATION_STALE_TIMEOUT_MS;
304
+ if (now >= expiresAt) {
305
+ segmentationMasksByTopicRef.current.delete(annotationTopic);
306
+ }
307
+ else {
308
+ nextExpiry = Math.min(nextExpiry, expiresAt);
309
+ if (isEnabled) {
310
+ enabledSegmentationMasks.push(segmentationMaskEntry.mask);
311
+ }
312
+ }
209
313
  }
210
314
  }
211
- const segmentationMaskEntry = segmentationMasksByTopicRef.current.get(annotationTopic);
212
- if (segmentationMaskEntry) {
213
- if (now - segmentationMaskEntry.receivedAt > ANNOTATION_STALE_TIMEOUT_MS) {
214
- segmentationMasksByTopicRef.current.delete(annotationTopic);
315
+ overlayCtx.scale(dpr, dpr);
316
+ if (enabledSegmentationMasks.length > 0) {
317
+ if (segmentationCanvas.width !== width || segmentationCanvas.height !== height) {
318
+ segmentationCanvas.width = width;
319
+ segmentationCanvas.height = height;
320
+ }
321
+ const segmentationRenderer = ensureSegmentationRenderer();
322
+ if (segmentationRenderer) {
323
+ segmentationRenderer.draw(enabledSegmentationMasks, width, height, scaledRect);
215
324
  }
216
- else if (isEnabled) {
217
- enabledSegmentationMasks.push(segmentationMaskEntry.mask);
325
+ else {
326
+ releaseCanvasBackingStore(segmentationCanvas);
327
+ drawSegmentationMasks(overlayCtx, enabledSegmentationMasks, rect);
218
328
  }
219
329
  }
330
+ else if (segmentationRendererRef.current) {
331
+ segmentationRendererRef.current.draw([], width, height, scaledRect);
332
+ }
333
+ else {
334
+ // Most image streams never carry segmentation. Avoid allocating a second
335
+ // full-size canvas and WebGL context for every panel until one is needed.
336
+ releaseCanvasBackingStore(segmentationCanvas);
337
+ }
338
+ drawImageAnnotations(overlayCtx, enabledTopics, rect, decodedRenderable.width, decodedRenderable.height);
339
+ nextOverlayExpiryRef.current = nextExpiry;
340
+ overlayDirtyRef.current = false;
220
341
  }
221
- overlayCtx.scale(dpr, dpr);
222
- drawSegmentationMasks(overlayCtx, enabledSegmentationMasks, rect);
223
- drawImageAnnotations(overlayCtx, enabledTopics, rect, decodedRenderable.width, decodedRenderable.height);
224
- if (lastReportedImageRevisionRef.current !== imageRevisionRef.current) {
225
- lastReportedImageRevisionRef.current = imageRevisionRef.current;
342
+ if (lastReportedImageRevisionRef.current !== imageRevision &&
343
+ lastDrawnImageRevisionRef.current === imageRevision) {
344
+ lastReportedImageRevisionRef.current = imageRevision;
226
345
  frameRenderedEventRef.current?.(performance.now() - drawStart);
346
+ recordBenchmarkRendered(topic);
227
347
  recordRenderFrame({
228
348
  topic,
229
349
  source: renderSource,
230
350
  renderDurationMs: performance.now() - drawStart,
231
351
  });
232
352
  }
233
- }, [allAnnotationTopics, ensureWebGlRenderer]);
353
+ }, [
354
+ allAnnotationTopics,
355
+ ensureSegmentationRenderer,
356
+ ensureWebGlRenderer,
357
+ setRendererModeIfChanged,
358
+ ]);
234
359
  const scheduleDraw = React.useCallback(() => {
235
360
  if (drawRequestIdRef.current != undefined) {
236
361
  return;
@@ -250,6 +375,8 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
250
375
  }, [topic]);
251
376
  const resetZoom = React.useCallback(() => {
252
377
  viewTransformRef.current = { scale: 1, offsetX: 0, offsetY: 0 };
378
+ baseDirtyRef.current = true;
379
+ overlayDirtyRef.current = true;
253
380
  dragStateRef.current = undefined;
254
381
  suppressClickRef.current = false;
255
382
  publishZoomState(false);
@@ -258,6 +385,9 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
258
385
  const clearRenderable = React.useCallback(() => {
259
386
  releaseDecodedRenderable(decodedRenderableRef.current);
260
387
  decodedRenderableRef.current = undefined;
388
+ baseDirtyRef.current = true;
389
+ lastDrawnImageRevisionRef.current = -1;
390
+ overlayDirtyRef.current = true;
261
391
  setRendererModeIfChanged("canvas2d");
262
392
  publishZoomState(false);
263
393
  if (hasRenderableRef.current) {
@@ -276,6 +406,11 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
276
406
  });
277
407
  }, []);
278
408
  const applyDirectRawImage = React.useCallback((image) => {
409
+ const previousRenderable = decodedRenderableRef.current;
410
+ if (previousRenderable?.width !== image.width ||
411
+ previousRenderable?.height !== image.height) {
412
+ overlayDirtyRef.current = true;
413
+ }
279
414
  releaseDecodedRenderable(decodedRenderableRef.current);
280
415
  setRendererModeIfChanged("webgl");
281
416
  decodedRenderableRef.current = {
@@ -291,6 +426,11 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
291
426
  scheduleDraw();
292
427
  }, [releaseDecodedRenderable, scheduleDraw, setRendererModeIfChanged]);
293
428
  const applyCanvasRenderable = React.useCallback((renderable) => {
429
+ const previousRenderable = decodedRenderableRef.current;
430
+ if (previousRenderable?.width !== renderable.width ||
431
+ previousRenderable?.height !== renderable.height) {
432
+ overlayDirtyRef.current = true;
433
+ }
294
434
  releaseDecodedRenderable(decodedRenderableRef.current);
295
435
  setRendererModeIfChanged("canvas2d");
296
436
  decodedRenderableRef.current = renderable;
@@ -363,6 +503,8 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
363
503
  width: entry.contentRect.width,
364
504
  height: entry.contentRect.height,
365
505
  };
506
+ baseDirtyRef.current = true;
507
+ overlayDirtyRef.current = true;
366
508
  const decodedRenderable = decodedRenderableRef.current;
367
509
  if (decodedRenderable) {
368
510
  viewTransformRef.current = clampViewTransform(calculateDrawRect(decodedRenderable.width, decodedRenderable.height, entry.contentRect.width, entry.contentRect.height), entry.contentRect.width, entry.contentRect.height, viewTransformRef.current);
@@ -422,10 +564,13 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
422
564
  decoderRef.current = undefined;
423
565
  webGlRendererRef.current?.destroy();
424
566
  webGlRendererRef.current = undefined;
567
+ segmentationRendererRef.current?.destroy();
568
+ segmentationRendererRef.current = undefined;
425
569
  };
426
570
  }, [releaseDecodedRenderable, topic]);
427
571
  React.useEffect(() => {
428
572
  detectionsRef.current = detections.detections;
573
+ overlayDirtyRef.current = true;
429
574
  scheduleDraw();
430
575
  }, [detections.detections, scheduleDraw]);
431
576
  useMessageSubscription({
@@ -461,8 +606,34 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
461
606
  decodeRequestIdRef.current = requestId;
462
607
  pendingDecodeImageRef.current = undefined;
463
608
  pendingDecodeRequestIdRef.current = undefined;
464
- if (image.renderableBitmap) {
609
+ if (image.renderableVideoFrame) {
610
+ const frame = image.renderableVideoFrame;
611
+ const previousRenderable = decodedRenderableRef.current;
612
+ if (previousRenderable?.width !== image.width ||
613
+ previousRenderable?.height !== image.height) {
614
+ overlayDirtyRef.current = true;
615
+ }
616
+ releaseDecodedRenderable(decodedRenderableRef.current);
617
+ setRendererModeIfChanged("canvas2d");
618
+ decodedRenderableRef.current = {
619
+ kind: "video-frame",
620
+ frame,
621
+ width: image.width,
622
+ height: image.height,
623
+ };
624
+ if (!hasRenderableRef.current) {
625
+ hasRenderableRef.current = true;
626
+ setHasRenderable(true);
627
+ }
628
+ scheduleDraw();
629
+ }
630
+ else if (image.renderableBitmap) {
465
631
  const bitmap = image.renderableBitmap;
632
+ const previousRenderable = decodedRenderableRef.current;
633
+ if (previousRenderable?.width !== image.width ||
634
+ previousRenderable?.height !== image.height) {
635
+ overlayDirtyRef.current = true;
636
+ }
466
637
  releaseDecodedRenderable(decodedRenderableRef.current);
467
638
  setRendererModeIfChanged("canvas2d");
468
639
  activeBitmapRef.current = bitmap;
@@ -500,6 +671,7 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
500
671
  });
501
672
  }
502
673
  annotationReceivedEventHandlerRef.current?.();
674
+ overlayDirtyRef.current = true;
503
675
  scheduleDraw();
504
676
  }
505
677
  if (latestSegmentationMaskByTopic.size > 0) {
@@ -511,6 +683,7 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
511
683
  });
512
684
  }
513
685
  annotationReceivedEventHandlerRef.current?.();
686
+ overlayDirtyRef.current = true;
514
687
  scheduleDraw();
515
688
  }
516
689
  },
@@ -565,6 +738,8 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
565
738
  offsetX: localX - baseRect.x - normalizedX * nextRectWidth,
566
739
  offsetY: localY - baseRect.y - normalizedY * nextRectHeight,
567
740
  });
741
+ baseDirtyRef.current = true;
742
+ overlayDirtyRef.current = true;
568
743
  publishZoomState(nextScale > MIN_ZOOM);
569
744
  scheduleDraw();
570
745
  }, onPointerDown: (event) => {
@@ -601,6 +776,8 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
601
776
  offsetX: dragState.startOffsetX + deltaX,
602
777
  offsetY: dragState.startOffsetY + deltaY,
603
778
  });
779
+ baseDirtyRef.current = true;
780
+ overlayDirtyRef.current = true;
604
781
  scheduleDraw();
605
782
  return;
606
783
  }
@@ -623,7 +800,7 @@ export function ImageCanvasRenderer({ topic, annotationTopics, extraAnnotationTo
623
800
  handleOnClick?.(event, handlePointerEvent(event.clientX, event.clientY));
624
801
  }, onDoubleClick: () => {
625
802
  resetZoom();
626
- }, children: [_jsx("canvas", { className: `absolute inset-0 h-full w-full ${rendererMode === "webgl" ? "hidden" : ""}`, ref: canvas2dRef }), _jsx("canvas", { className: `absolute inset-0 h-full w-full ${rendererMode === "canvas2d" ? "hidden" : ""}`, ref: webGlCanvasRef }), _jsx("canvas", { className: "absolute inset-0 h-full w-full pointer-events-none", ref: overlayCanvasRef }), customOverlay ? (_jsx("div", { className: "absolute inset-0 pointer-events-none", children: customOverlay })) : null, !hasRenderable ? (_jsx("div", { className: "absolute inset-0 flex items-center justify-center text-sm text-slate-600", children: "Waiting for image frames" })) : null] }));
803
+ }, children: [_jsx("canvas", { className: `absolute inset-0 h-full w-full ${rendererMode === "webgl" ? "hidden" : ""}`, ref: canvas2dRef }), _jsx("canvas", { className: `absolute inset-0 h-full w-full ${rendererMode === "canvas2d" ? "hidden" : ""}`, ref: webGlCanvasRef }), _jsx("canvas", { className: "absolute inset-0 h-full w-full pointer-events-none", ref: segmentationCanvasRef }), _jsx("canvas", { className: "absolute inset-0 h-full w-full pointer-events-none", ref: overlayCanvasRef }), customOverlay ? (_jsx("div", { className: "absolute inset-0 pointer-events-none", children: customOverlay })) : null, !hasRenderable ? (_jsx("div", { className: "absolute inset-0 flex items-center justify-center text-sm text-slate-600", children: "Waiting for image frames" })) : null] }));
627
804
  }
628
805
  function calculateDrawRect(imageWidth, imageHeight, containerWidth, containerHeight) {
629
806
  if (imageWidth <= 0 || imageHeight <= 0 || containerWidth <= 0 || containerHeight <= 0) {