@luxonis/depthai-viewer-common 3.7.4 → 3.7.6

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 (524) hide show
  1. package/LICENSE +202 -0
  2. package/LICENSE.MPL-2.0 +373 -0
  3. package/NOTICE +15 -0
  4. package/REFACTOR_HANDOFF.md +969 -0
  5. package/REFACTOR_PLAN.md +265 -0
  6. package/THIRD_PARTY_NOTICES.md +3624 -0
  7. package/build-utils.sh +45 -0
  8. package/dist/components/DepthAIContext.d.ts +1 -1
  9. package/dist/components/DepthAIContext.d.ts.map +1 -1
  10. package/dist/components/DepthAIContext.js.map +1 -1
  11. package/dist/components/Streams.d.ts.map +1 -1
  12. package/dist/components/Streams.js +10 -3
  13. package/dist/components/Streams.js.map +1 -1
  14. package/dist/dai-connection/connection.d.ts +5 -3
  15. package/dist/dai-connection/connection.d.ts.map +1 -1
  16. package/dist/dai-connection/connection.js +3 -3
  17. package/dist/dai-connection/connection.js.map +1 -1
  18. package/dist/hooks/benchmark-automation.d.ts.map +1 -1
  19. package/dist/hooks/benchmark-automation.js +1 -1
  20. package/dist/hooks/benchmark-automation.js.map +1 -1
  21. package/dist/hooks/connection.d.ts +1 -1
  22. package/dist/hooks/connection.d.ts.map +1 -1
  23. package/dist/hooks/connection.js +21 -0
  24. package/dist/hooks/connection.js.map +1 -1
  25. package/dist/index.css +160 -0
  26. package/dist/models/device-configuration.d.ts +1 -1
  27. package/dist/providers/ConnectionProvider.d.ts.map +1 -1
  28. package/dist/providers/ConnectionProvider.js +1 -1
  29. package/dist/providers/ConnectionProvider.js.map +1 -1
  30. package/dist/providers/VisualizerRuntimeConfigProvider.d.ts +2 -1
  31. package/dist/providers/VisualizerRuntimeConfigProvider.d.ts.map +1 -1
  32. package/dist/providers/VisualizerRuntimeConfigProvider.js +6 -2
  33. package/dist/providers/VisualizerRuntimeConfigProvider.js.map +1 -1
  34. package/dist/utils/vite-dev-fix.js +1 -1
  35. package/dist/utils/vite-dev-fix.js.map +1 -1
  36. package/dist/visualizer/browser-decoder-fixtures-entry.d.ts +2 -0
  37. package/dist/visualizer/browser-decoder-fixtures-entry.d.ts.map +1 -0
  38. package/dist/visualizer/browser-decoder-fixtures-entry.js +28 -0
  39. package/dist/visualizer/browser-decoder-fixtures-entry.js.map +1 -0
  40. package/dist/visualizer/components/CssBaseline.d.ts +5 -0
  41. package/dist/visualizer/components/CssBaseline.d.ts.map +1 -0
  42. package/dist/visualizer/components/CssBaseline.js +5 -0
  43. package/dist/visualizer/components/CssBaseline.js.map +1 -0
  44. package/dist/visualizer/components/EmptyState.d.ts +7 -0
  45. package/dist/visualizer/components/EmptyState.d.ts.map +1 -0
  46. package/dist/visualizer/components/EmptyState.js +5 -0
  47. package/dist/visualizer/components/EmptyState.js.map +1 -0
  48. package/dist/visualizer/components/ErrorBoundary.d.ts +16 -0
  49. package/dist/visualizer/components/ErrorBoundary.d.ts.map +1 -0
  50. package/dist/visualizer/components/ErrorBoundary.js +27 -0
  51. package/dist/visualizer/components/ErrorBoundary.js.map +1 -0
  52. package/dist/visualizer/components/GlobalCss.d.ts +2 -0
  53. package/dist/visualizer/components/GlobalCss.d.ts.map +1 -0
  54. package/dist/visualizer/components/GlobalCss.js +4 -0
  55. package/dist/visualizer/components/GlobalCss.js.map +1 -0
  56. package/dist/visualizer/components/Panel.d.ts +37 -0
  57. package/dist/visualizer/components/Panel.d.ts.map +1 -0
  58. package/dist/visualizer/components/Panel.js +129 -0
  59. package/dist/visualizer/components/Panel.js.map +1 -0
  60. package/dist/visualizer/components/PanelLayout.d.ts +3 -0
  61. package/dist/visualizer/components/PanelLayout.d.ts.map +1 -0
  62. package/dist/visualizer/components/PanelLayout.js +5 -0
  63. package/dist/visualizer/components/PanelLayout.js.map +1 -0
  64. package/dist/visualizer/components/PanelToolbar.d.ts +24 -0
  65. package/dist/visualizer/components/PanelToolbar.d.ts.map +1 -0
  66. package/dist/visualizer/components/PanelToolbar.js +69 -0
  67. package/dist/visualizer/components/PanelToolbar.js.map +1 -0
  68. package/dist/visualizer/components/RemountOnValueChange.d.ts +7 -0
  69. package/dist/visualizer/components/RemountOnValueChange.d.ts.map +1 -0
  70. package/dist/visualizer/components/RemountOnValueChange.js +20 -0
  71. package/dist/visualizer/components/RemountOnValueChange.js.map +1 -0
  72. package/dist/visualizer/components/measure-event-loop-delay.d.ts +2 -0
  73. package/dist/visualizer/components/measure-event-loop-delay.d.ts.map +1 -0
  74. package/dist/visualizer/components/measure-event-loop-delay.js +18 -0
  75. package/dist/visualizer/components/measure-event-loop-delay.js.map +1 -0
  76. package/dist/visualizer/components/shared-interval.d.ts +2 -0
  77. package/dist/visualizer/components/shared-interval.d.ts.map +1 -0
  78. package/dist/visualizer/components/shared-interval.js +50 -0
  79. package/dist/visualizer/components/shared-interval.js.map +1 -0
  80. package/dist/visualizer/components/use-element-width.d.ts +3 -0
  81. package/dist/visualizer/components/use-element-width.d.ts.map +1 -0
  82. package/dist/visualizer/components/use-element-width.js +23 -0
  83. package/dist/visualizer/components/use-element-width.js.map +1 -0
  84. package/dist/visualizer/connection/adapter.d.ts +43 -0
  85. package/dist/visualizer/connection/adapter.d.ts.map +1 -0
  86. package/dist/visualizer/connection/adapter.js +196 -0
  87. package/dist/visualizer/connection/adapter.js.map +1 -0
  88. package/dist/visualizer/connection/communicator.d.ts +94 -0
  89. package/dist/visualizer/connection/communicator.d.ts.map +1 -0
  90. package/dist/visualizer/connection/communicator.js +134 -0
  91. package/dist/visualizer/connection/communicator.js.map +1 -0
  92. package/dist/visualizer/connection/connection.d.ts +54 -0
  93. package/dist/visualizer/connection/connection.d.ts.map +1 -0
  94. package/dist/visualizer/connection/connection.js +155 -0
  95. package/dist/visualizer/connection/connection.js.map +1 -0
  96. package/dist/visualizer/connection/foxglove-client-adapter.d.ts +31 -0
  97. package/dist/visualizer/connection/foxglove-client-adapter.d.ts.map +1 -0
  98. package/dist/visualizer/connection/foxglove-client-adapter.js +125 -0
  99. package/dist/visualizer/connection/foxglove-client-adapter.js.map +1 -0
  100. package/dist/visualizer/connection/foxglove-connection.d.ts +86 -0
  101. package/dist/visualizer/connection/foxglove-connection.d.ts.map +1 -0
  102. package/dist/visualizer/connection/foxglove-connection.js +329 -0
  103. package/dist/visualizer/connection/foxglove-connection.js.map +1 -0
  104. package/dist/visualizer/connection/foxglove-protocol.d.ts +6 -0
  105. package/dist/visualizer/connection/foxglove-protocol.d.ts.map +1 -0
  106. package/dist/visualizer/connection/foxglove-protocol.js +63 -0
  107. package/dist/visualizer/connection/foxglove-protocol.js.map +1 -0
  108. package/dist/visualizer/connection/foxglove-ws-types.d.ts +80 -0
  109. package/dist/visualizer/connection/foxglove-ws-types.d.ts.map +1 -0
  110. package/dist/visualizer/connection/foxglove-ws-types.js +13 -0
  111. package/dist/visualizer/connection/foxglove-ws-types.js.map +1 -0
  112. package/dist/visualizer/connection/webrtc/bridge.d.ts +11 -0
  113. package/dist/visualizer/connection/webrtc/bridge.d.ts.map +1 -0
  114. package/dist/visualizer/connection/webrtc/bridge.js +453 -0
  115. package/dist/visualizer/connection/webrtc/bridge.js.map +1 -0
  116. package/dist/visualizer/connection/webrtc/comms-proxy.d.ts +9 -0
  117. package/dist/visualizer/connection/webrtc/comms-proxy.d.ts.map +1 -0
  118. package/dist/visualizer/connection/webrtc/comms-proxy.js +90 -0
  119. package/dist/visualizer/connection/webrtc/comms-proxy.js.map +1 -0
  120. package/dist/visualizer/connection/webrtc/handler.d.ts +97 -0
  121. package/dist/visualizer/connection/webrtc/handler.d.ts.map +1 -0
  122. package/dist/visualizer/connection/webrtc/handler.js +149 -0
  123. package/dist/visualizer/connection/webrtc/handler.js.map +1 -0
  124. package/dist/visualizer/connection/webrtc/worker.d.ts +2 -0
  125. package/dist/visualizer/connection/webrtc/worker.d.ts.map +1 -0
  126. package/dist/visualizer/connection/webrtc/worker.js +32 -0
  127. package/dist/visualizer/connection/webrtc/worker.js.map +1 -0
  128. package/dist/visualizer/connection/ws/worker.d.ts +17 -0
  129. package/dist/visualizer/connection/ws/worker.d.ts.map +1 -0
  130. package/dist/visualizer/connection/ws/worker.js +161 -0
  131. package/dist/visualizer/connection/ws/worker.js.map +1 -0
  132. package/dist/visualizer/context/AppConfigurationContext.d.ts +9 -0
  133. package/dist/visualizer/context/AppConfigurationContext.d.ts.map +1 -0
  134. package/dist/visualizer/context/AppConfigurationContext.js +4 -0
  135. package/dist/visualizer/context/AppConfigurationContext.js.map +1 -0
  136. package/dist/visualizer/context/ConnectionsProvider.d.ts +5 -0
  137. package/dist/visualizer/context/ConnectionsProvider.d.ts.map +1 -0
  138. package/dist/visualizer/context/ConnectionsProvider.js +8 -0
  139. package/dist/visualizer/context/ConnectionsProvider.js.map +1 -0
  140. package/dist/visualizer/context/CurrentLayoutContext.d.ts +63 -0
  141. package/dist/visualizer/context/CurrentLayoutContext.d.ts.map +1 -0
  142. package/dist/visualizer/context/CurrentLayoutContext.js +4 -0
  143. package/dist/visualizer/context/CurrentLayoutContext.js.map +1 -0
  144. package/dist/visualizer/context/MessagePipelineInternalContext.d.ts +3 -0
  145. package/dist/visualizer/context/MessagePipelineInternalContext.d.ts.map +1 -0
  146. package/dist/visualizer/context/MessagePipelineInternalContext.js +3 -0
  147. package/dist/visualizer/context/MessagePipelineInternalContext.js.map +1 -0
  148. package/dist/visualizer/context/MessagePipelineProvider.d.ts +17 -0
  149. package/dist/visualizer/context/MessagePipelineProvider.d.ts.map +1 -0
  150. package/dist/visualizer/context/MessagePipelineProvider.js +224 -0
  151. package/dist/visualizer/context/MessagePipelineProvider.js.map +1 -0
  152. package/dist/visualizer/context/MinimalCurrentLayoutProvider.d.ts +5 -0
  153. package/dist/visualizer/context/MinimalCurrentLayoutProvider.d.ts.map +1 -0
  154. package/dist/visualizer/context/MinimalCurrentLayoutProvider.js +198 -0
  155. package/dist/visualizer/context/MinimalCurrentLayoutProvider.js.map +1 -0
  156. package/dist/visualizer/context/PanelCatalogContext.d.ts +11 -0
  157. package/dist/visualizer/context/PanelCatalogContext.d.ts.map +1 -0
  158. package/dist/visualizer/context/PanelCatalogContext.js +4 -0
  159. package/dist/visualizer/context/PanelCatalogContext.js.map +1 -0
  160. package/dist/visualizer/context/PanelStateContextProvider.d.ts +5 -0
  161. package/dist/visualizer/context/PanelStateContextProvider.d.ts.map +1 -0
  162. package/dist/visualizer/context/PanelStateContextProvider.js +5 -0
  163. package/dist/visualizer/context/PanelStateContextProvider.js.map +1 -0
  164. package/dist/visualizer/context/TimelineInteractionStateProvider.d.ts +5 -0
  165. package/dist/visualizer/context/TimelineInteractionStateProvider.d.ts.map +1 -0
  166. package/dist/visualizer/context/TimelineInteractionStateProvider.js +5 -0
  167. package/dist/visualizer/context/TimelineInteractionStateProvider.js.map +1 -0
  168. package/dist/visualizer/context/VisualizerContext.d.ts +13 -0
  169. package/dist/visualizer/context/VisualizerContext.d.ts.map +1 -0
  170. package/dist/visualizer/context/VisualizerContext.js +81 -0
  171. package/dist/visualizer/context/VisualizerContext.js.map +1 -0
  172. package/dist/visualizer/context/VisualizerFlatContext.d.ts +10 -0
  173. package/dist/visualizer/context/VisualizerFlatContext.d.ts.map +1 -0
  174. package/dist/visualizer/context/VisualizerFlatContext.js +13 -0
  175. package/dist/visualizer/context/VisualizerFlatContext.js.map +1 -0
  176. package/dist/visualizer/context/message-pipeline-store.d.ts +35 -0
  177. package/dist/visualizer/context/message-pipeline-store.d.ts.map +1 -0
  178. package/dist/visualizer/context/message-pipeline-store.js +275 -0
  179. package/dist/visualizer/context/message-pipeline-store.js.map +1 -0
  180. package/dist/visualizer/context/message-pipeline-types.d.ts +52 -0
  181. package/dist/visualizer/context/message-pipeline-types.d.ts.map +1 -0
  182. package/dist/visualizer/context/message-pipeline-types.js +5 -0
  183. package/dist/visualizer/context/message-pipeline-types.js.map +1 -0
  184. package/dist/visualizer/context/pause-frame.d.ts +4 -0
  185. package/dist/visualizer/context/pause-frame.d.ts.map +1 -0
  186. package/dist/visualizer/context/pause-frame.js +21 -0
  187. package/dist/visualizer/context/pause-frame.js.map +1 -0
  188. package/dist/visualizer/fonts/fonts.css +6 -0
  189. package/dist/visualizer/fonts/ubuntu-mono.ttf +0 -0
  190. package/dist/visualizer/i18n-stubs/i18next-browser-languagedetector.d.ts +7 -0
  191. package/dist/visualizer/i18n-stubs/i18next-browser-languagedetector.d.ts.map +1 -0
  192. package/dist/visualizer/i18n-stubs/i18next-browser-languagedetector.js +12 -0
  193. package/dist/visualizer/i18n-stubs/i18next-browser-languagedetector.js.map +1 -0
  194. package/dist/visualizer/i18n-stubs/i18next.d.ts +24 -0
  195. package/dist/visualizer/i18n-stubs/i18next.d.ts.map +1 -0
  196. package/dist/visualizer/i18n-stubs/i18next.js +46 -0
  197. package/dist/visualizer/i18n-stubs/i18next.js.map +1 -0
  198. package/dist/visualizer/i18n-stubs/react-i18next.d.ts +10 -0
  199. package/dist/visualizer/i18n-stubs/react-i18next.d.ts.map +1 -0
  200. package/dist/visualizer/i18n-stubs/react-i18next.js +15 -0
  201. package/dist/visualizer/i18n-stubs/react-i18next.js.map +1 -0
  202. package/dist/visualizer/index.d.ts +14 -0
  203. package/dist/visualizer/index.d.ts.map +1 -0
  204. package/dist/visualizer/index.js +16 -0
  205. package/dist/visualizer/index.js.map +1 -0
  206. package/dist/visualizer/messaging/browser-decoder-fixtures.d.ts +15 -0
  207. package/dist/visualizer/messaging/browser-decoder-fixtures.d.ts.map +1 -0
  208. package/dist/visualizer/messaging/browser-decoder-fixtures.js +205 -0
  209. package/dist/visualizer/messaging/browser-decoder-fixtures.js.map +1 -0
  210. package/dist/visualizer/messaging/decode-core.d.ts +75 -0
  211. package/dist/visualizer/messaging/decode-core.d.ts.map +1 -0
  212. package/dist/visualizer/messaging/decode-core.js +244 -0
  213. package/dist/visualizer/messaging/decode-core.js.map +1 -0
  214. package/dist/visualizer/messaging/decoder-fixtures.d.ts +14 -0
  215. package/dist/visualizer/messaging/decoder-fixtures.d.ts.map +1 -0
  216. package/dist/visualizer/messaging/decoder-fixtures.js +743 -0
  217. package/dist/visualizer/messaging/decoder-fixtures.js.map +1 -0
  218. package/dist/visualizer/messaging/decoder-harness.d.ts +24 -0
  219. package/dist/visualizer/messaging/decoder-harness.d.ts.map +1 -0
  220. package/dist/visualizer/messaging/decoder-harness.js +24 -0
  221. package/dist/visualizer/messaging/decoder-harness.js.map +1 -0
  222. package/dist/visualizer/messaging/deserialization/detections/constants.d.ts +16 -0
  223. package/dist/visualizer/messaging/deserialization/detections/constants.d.ts.map +1 -0
  224. package/dist/visualizer/messaging/deserialization/detections/constants.js +106 -0
  225. package/dist/visualizer/messaging/deserialization/detections/constants.js.map +1 -0
  226. package/dist/visualizer/messaging/deserialization/detections/custom.d.ts +11 -0
  227. package/dist/visualizer/messaging/deserialization/detections/custom.d.ts.map +1 -0
  228. package/dist/visualizer/messaging/deserialization/detections/custom.js +62 -0
  229. package/dist/visualizer/messaging/deserialization/detections/custom.js.map +1 -0
  230. package/dist/visualizer/messaging/deserialization/detections/detection.d.ts +14 -0
  231. package/dist/visualizer/messaging/deserialization/detections/detection.d.ts.map +1 -0
  232. package/dist/visualizer/messaging/deserialization/detections/detection.js +296 -0
  233. package/dist/visualizer/messaging/deserialization/detections/detection.js.map +1 -0
  234. package/dist/visualizer/messaging/deserialization/detections/utils.d.ts +9 -0
  235. package/dist/visualizer/messaging/deserialization/detections/utils.d.ts.map +1 -0
  236. package/dist/visualizer/messaging/deserialization/detections/utils.js +22 -0
  237. package/dist/visualizer/messaging/deserialization/detections/utils.js.map +1 -0
  238. package/dist/visualizer/messaging/deserialization/imu/imu.d.ts +5 -0
  239. package/dist/visualizer/messaging/deserialization/imu/imu.d.ts.map +1 -0
  240. package/dist/visualizer/messaging/deserialization/imu/imu.js +27 -0
  241. package/dist/visualizer/messaging/deserialization/imu/imu.js.map +1 -0
  242. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.d.ts +2 -0
  243. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.d.ts.map +1 -0
  244. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.js +45 -0
  245. package/dist/visualizer/messaging/deserialization/pointcloud/i420ToRgbaToPoitcloud.worker.js.map +1 -0
  246. package/dist/visualizer/messaging/deserialization/pointcloud/point-cloud.d.ts +9 -0
  247. package/dist/visualizer/messaging/deserialization/pointcloud/point-cloud.d.ts.map +1 -0
  248. package/dist/visualizer/messaging/deserialization/pointcloud/point-cloud.js +46 -0
  249. package/dist/visualizer/messaging/deserialization/pointcloud/point-cloud.js.map +1 -0
  250. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.d.ts +2 -0
  251. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.d.ts.map +1 -0
  252. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js +477 -0
  253. package/dist/visualizer/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.js.map +1 -0
  254. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.d.ts +35 -0
  255. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.d.ts.map +1 -0
  256. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.js +344 -0
  257. package/dist/visualizer/messaging/deserialization/pointcloud/poitcloudPoolManager.js.map +1 -0
  258. package/dist/visualizer/messaging/deserialization/pointcloud/utils.d.ts +18 -0
  259. package/dist/visualizer/messaging/deserialization/pointcloud/utils.d.ts.map +1 -0
  260. package/dist/visualizer/messaging/deserialization/pointcloud/utils.js +58 -0
  261. package/dist/visualizer/messaging/deserialization/pointcloud/utils.js.map +1 -0
  262. package/dist/visualizer/messaging/deserialization/segmentation/segmentation-mask.d.ts +9 -0
  263. package/dist/visualizer/messaging/deserialization/segmentation/segmentation-mask.d.ts.map +1 -0
  264. package/dist/visualizer/messaging/deserialization/segmentation/segmentation-mask.js +39 -0
  265. package/dist/visualizer/messaging/deserialization/segmentation/segmentation-mask.js.map +1 -0
  266. package/dist/visualizer/messaging/deserialization/video/color.d.ts +9 -0
  267. package/dist/visualizer/messaging/deserialization/video/color.d.ts.map +1 -0
  268. package/dist/visualizer/messaging/deserialization/video/color.js +27 -0
  269. package/dist/visualizer/messaging/deserialization/video/color.js.map +1 -0
  270. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.d.ts +5 -0
  271. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.d.ts.map +1 -0
  272. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.js +124 -0
  273. package/dist/visualizer/messaging/deserialization/video/depth-coloring.worker.js.map +1 -0
  274. package/dist/visualizer/messaging/deserialization/video/depth-to-pointcloud.d.ts +13 -0
  275. package/dist/visualizer/messaging/deserialization/video/depth-to-pointcloud.d.ts.map +1 -0
  276. package/dist/visualizer/messaging/deserialization/video/depth-to-pointcloud.js +37 -0
  277. package/dist/visualizer/messaging/deserialization/video/depth-to-pointcloud.js.map +1 -0
  278. package/dist/visualizer/messaging/deserialization/video/depth.d.ts +15 -0
  279. package/dist/visualizer/messaging/deserialization/video/depth.d.ts.map +1 -0
  280. package/dist/visualizer/messaging/deserialization/video/depth.js +126 -0
  281. package/dist/visualizer/messaging/deserialization/video/depth.js.map +1 -0
  282. package/dist/visualizer/messaging/deserialization/video/h264.d.ts +81 -0
  283. package/dist/visualizer/messaging/deserialization/video/h264.d.ts.map +1 -0
  284. package/dist/visualizer/messaging/deserialization/video/h264.js +634 -0
  285. package/dist/visualizer/messaging/deserialization/video/h264.js.map +1 -0
  286. package/dist/visualizer/messaging/deserialization/video/h265.d.ts +16 -0
  287. package/dist/visualizer/messaging/deserialization/video/h265.d.ts.map +1 -0
  288. package/dist/visualizer/messaging/deserialization/video/h265.js +448 -0
  289. package/dist/visualizer/messaging/deserialization/video/h265.js.map +1 -0
  290. package/dist/visualizer/messaging/deserialization/video/mjpeg.d.ts +11 -0
  291. package/dist/visualizer/messaging/deserialization/video/mjpeg.d.ts.map +1 -0
  292. package/dist/visualizer/messaging/deserialization/video/mjpeg.js +89 -0
  293. package/dist/visualizer/messaging/deserialization/video/mjpeg.js.map +1 -0
  294. package/dist/visualizer/messaging/deserialization/video/mono.d.ts +8 -0
  295. package/dist/visualizer/messaging/deserialization/video/mono.d.ts.map +1 -0
  296. package/dist/visualizer/messaging/deserialization/video/mono.js +27 -0
  297. package/dist/visualizer/messaging/deserialization/video/mono.js.map +1 -0
  298. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.d.ts +18 -0
  299. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.d.ts.map +1 -0
  300. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.js +651 -0
  301. package/dist/visualizer/messaging/deserialization/video/rgbd-to-pointcloud.js.map +1 -0
  302. package/dist/visualizer/messaging/deserialization.worker.d.ts +15 -0
  303. package/dist/visualizer/messaging/deserialization.worker.d.ts.map +1 -0
  304. package/dist/visualizer/messaging/deserialization.worker.js +96 -0
  305. package/dist/visualizer/messaging/deserialization.worker.js.map +1 -0
  306. package/dist/visualizer/messaging/message-event.d.ts +114 -0
  307. package/dist/visualizer/messaging/message-event.d.ts.map +1 -0
  308. package/dist/visualizer/messaging/message-event.js +80 -0
  309. package/dist/visualizer/messaging/message-event.js.map +1 -0
  310. package/dist/visualizer/messaging/message-handler.d.ts +10 -0
  311. package/dist/visualizer/messaging/message-handler.d.ts.map +1 -0
  312. package/dist/visualizer/messaging/message-handler.js +436 -0
  313. package/dist/visualizer/messaging/message-handler.js.map +1 -0
  314. package/dist/visualizer/messaging/message.d.ts +32 -0
  315. package/dist/visualizer/messaging/message.d.ts.map +1 -0
  316. package/dist/visualizer/messaging/message.js +5 -0
  317. package/dist/visualizer/messaging/message.js.map +1 -0
  318. package/dist/visualizer/messaging/parse-utils.d.ts +23 -0
  319. package/dist/visualizer/messaging/parse-utils.d.ts.map +1 -0
  320. package/dist/visualizer/messaging/parse-utils.js +76 -0
  321. package/dist/visualizer/messaging/parse-utils.js.map +1 -0
  322. package/dist/visualizer/messaging/protobuf.d.ts +109 -0
  323. package/dist/visualizer/messaging/protobuf.d.ts.map +1 -0
  324. package/dist/visualizer/messaging/protobuf.js +81 -0
  325. package/dist/visualizer/messaging/protobuf.js.map +1 -0
  326. package/dist/visualizer/messaging/schema-constants.d.ts +21 -0
  327. package/dist/visualizer/messaging/schema-constants.d.ts.map +1 -0
  328. package/dist/visualizer/messaging/schema-constants.js +24 -0
  329. package/dist/visualizer/messaging/schema-constants.js.map +1 -0
  330. package/dist/visualizer/messaging/stream-diagnostics.d.ts +40 -0
  331. package/dist/visualizer/messaging/stream-diagnostics.d.ts.map +1 -0
  332. package/dist/visualizer/messaging/stream-diagnostics.js +257 -0
  333. package/dist/visualizer/messaging/stream-diagnostics.js.map +1 -0
  334. package/dist/visualizer/messaging/utils.d.ts +14 -0
  335. package/dist/visualizer/messaging/utils.d.ts.map +1 -0
  336. package/dist/visualizer/messaging/utils.js +109 -0
  337. package/dist/visualizer/messaging/utils.js.map +1 -0
  338. package/dist/visualizer/output.css +4337 -0
  339. package/dist/visualizer/panels/ImagePanel.d.ts +35 -0
  340. package/dist/visualizer/panels/ImagePanel.d.ts.map +1 -0
  341. package/dist/visualizer/panels/ImagePanel.js +26 -0
  342. package/dist/visualizer/panels/ImagePanel.js.map +1 -0
  343. package/dist/visualizer/panels/PointCloudPanel.d.ts +32 -0
  344. package/dist/visualizer/panels/PointCloudPanel.d.ts.map +1 -0
  345. package/dist/visualizer/panels/PointCloudPanel.js +62 -0
  346. package/dist/visualizer/panels/PointCloudPanel.js.map +1 -0
  347. package/dist/visualizer/panels/image/ImageCanvasRenderer.d.ts +27 -0
  348. package/dist/visualizer/panels/image/ImageCanvasRenderer.d.ts.map +1 -0
  349. package/dist/visualizer/panels/image/ImageCanvasRenderer.js +715 -0
  350. package/dist/visualizer/panels/image/ImageCanvasRenderer.js.map +1 -0
  351. package/dist/visualizer/panels/image/annotation-overlay.d.ts +10 -0
  352. package/dist/visualizer/panels/image/annotation-overlay.d.ts.map +1 -0
  353. package/dist/visualizer/panels/image/annotation-overlay.js +113 -0
  354. package/dist/visualizer/panels/image/annotation-overlay.js.map +1 -0
  355. package/dist/visualizer/panels/image/raw-image-decoder.d.ts +11 -0
  356. package/dist/visualizer/panels/image/raw-image-decoder.d.ts.map +1 -0
  357. package/dist/visualizer/panels/image/raw-image-decoder.js +184 -0
  358. package/dist/visualizer/panels/image/raw-image-decoder.js.map +1 -0
  359. package/dist/visualizer/panels/image/raw-image-decoder.worker.d.ts +2 -0
  360. package/dist/visualizer/panels/image/raw-image-decoder.worker.d.ts.map +1 -0
  361. package/dist/visualizer/panels/image/raw-image-decoder.worker.js +40 -0
  362. package/dist/visualizer/panels/image/raw-image-decoder.worker.js.map +1 -0
  363. package/dist/visualizer/panels/image/raw-image-pixel-decoders.d.ts +35 -0
  364. package/dist/visualizer/panels/image/raw-image-pixel-decoders.d.ts.map +1 -0
  365. package/dist/visualizer/panels/image/raw-image-pixel-decoders.js +352 -0
  366. package/dist/visualizer/panels/image/raw-image-pixel-decoders.js.map +1 -0
  367. package/dist/visualizer/panels/image/segmentation-mask-overlay.d.ts +10 -0
  368. package/dist/visualizer/panels/image/segmentation-mask-overlay.d.ts.map +1 -0
  369. package/dist/visualizer/panels/image/segmentation-mask-overlay.js +56 -0
  370. package/dist/visualizer/panels/image/segmentation-mask-overlay.js.map +1 -0
  371. package/dist/visualizer/panels/image/webgl-image-renderer.d.ts +48 -0
  372. package/dist/visualizer/panels/image/webgl-image-renderer.d.ts.map +1 -0
  373. package/dist/visualizer/panels/image/webgl-image-renderer.js +726 -0
  374. package/dist/visualizer/panels/image/webgl-image-renderer.js.map +1 -0
  375. package/dist/visualizer/panels/image/worker-image-decoder.d.ts +20 -0
  376. package/dist/visualizer/panels/image/worker-image-decoder.d.ts.map +1 -0
  377. package/dist/visualizer/panels/image/worker-image-decoder.js +134 -0
  378. package/dist/visualizer/panels/image/worker-image-decoder.js.map +1 -0
  379. package/dist/visualizer/panels/panel-renderer.d.ts +2 -0
  380. package/dist/visualizer/panels/panel-renderer.d.ts.map +1 -0
  381. package/dist/visualizer/panels/panel-renderer.js +5 -0
  382. package/dist/visualizer/panels/panel-renderer.js.map +1 -0
  383. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.d.ts +35 -0
  384. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.d.ts.map +1 -0
  385. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.js +882 -0
  386. package/dist/visualizer/panels/pointcloud/PointCloudCanvasRenderer.js.map +1 -0
  387. package/dist/visualizer/panels/pointcloud-camera.d.ts +14 -0
  388. package/dist/visualizer/panels/pointcloud-camera.d.ts.map +1 -0
  389. package/dist/visualizer/panels/pointcloud-camera.js +16 -0
  390. package/dist/visualizer/panels/pointcloud-camera.js.map +1 -0
  391. package/dist/visualizer/protobuf.generated/EncodedFrame.d.ts +76 -0
  392. package/dist/visualizer/protobuf.generated/EncodedFrame.d.ts.map +1 -0
  393. package/dist/visualizer/protobuf.generated/EncodedFrame.js +448 -0
  394. package/dist/visualizer/protobuf.generated/EncodedFrame.js.map +1 -0
  395. package/dist/visualizer/protobuf.generated/Event.d.ts +171 -0
  396. package/dist/visualizer/protobuf.generated/Event.d.ts.map +1 -0
  397. package/dist/visualizer/protobuf.generated/Event.js +1805 -0
  398. package/dist/visualizer/protobuf.generated/Event.js.map +1 -0
  399. package/dist/visualizer/protobuf.generated/IMUData.d.ts +84 -0
  400. package/dist/visualizer/protobuf.generated/IMUData.d.ts.map +1 -0
  401. package/dist/visualizer/protobuf.generated/IMUData.js +745 -0
  402. package/dist/visualizer/protobuf.generated/IMUData.js.map +1 -0
  403. package/dist/visualizer/protobuf.generated/ImageAnnotations.d.ts +74 -0
  404. package/dist/visualizer/protobuf.generated/ImageAnnotations.d.ts.map +1 -0
  405. package/dist/visualizer/protobuf.generated/ImageAnnotations.js +675 -0
  406. package/dist/visualizer/protobuf.generated/ImageAnnotations.js.map +1 -0
  407. package/dist/visualizer/protobuf.generated/ImgDetections.d.ts +48 -0
  408. package/dist/visualizer/protobuf.generated/ImgDetections.d.ts.map +1 -0
  409. package/dist/visualizer/protobuf.generated/ImgDetections.js +429 -0
  410. package/dist/visualizer/protobuf.generated/ImgDetections.js.map +1 -0
  411. package/dist/visualizer/protobuf.generated/ImgFrame.d.ts +117 -0
  412. package/dist/visualizer/protobuf.generated/ImgFrame.d.ts.map +1 -0
  413. package/dist/visualizer/protobuf.generated/ImgFrame.js +699 -0
  414. package/dist/visualizer/protobuf.generated/ImgFrame.js.map +1 -0
  415. package/dist/visualizer/protobuf.generated/PointCloudData.d.ts +43 -0
  416. package/dist/visualizer/protobuf.generated/PointCloudData.d.ts.map +1 -0
  417. package/dist/visualizer/protobuf.generated/PointCloudData.js +348 -0
  418. package/dist/visualizer/protobuf.generated/PointCloudData.js.map +1 -0
  419. package/dist/visualizer/protobuf.generated/RGBDData.d.ts +37 -0
  420. package/dist/visualizer/protobuf.generated/RGBDData.d.ts.map +1 -0
  421. package/dist/visualizer/protobuf.generated/RGBDData.js +205 -0
  422. package/dist/visualizer/protobuf.generated/RGBDData.js.map +1 -0
  423. package/dist/visualizer/protobuf.generated/SegmentationMask.d.ts +36 -0
  424. package/dist/visualizer/protobuf.generated/SegmentationMask.d.ts.map +1 -0
  425. package/dist/visualizer/protobuf.generated/SegmentationMask.js +238 -0
  426. package/dist/visualizer/protobuf.generated/SegmentationMask.js.map +1 -0
  427. package/dist/visualizer/protobuf.generated/SpatialImgDetections.d.ts +88 -0
  428. package/dist/visualizer/protobuf.generated/SpatialImgDetections.d.ts.map +1 -0
  429. package/dist/visualizer/protobuf.generated/SpatialImgDetections.js +775 -0
  430. package/dist/visualizer/protobuf.generated/SpatialImgDetections.js.map +1 -0
  431. package/dist/visualizer/protobuf.generated/common.d.ts +175 -0
  432. package/dist/visualizer/protobuf.generated/common.d.ts.map +1 -0
  433. package/dist/visualizer/protobuf.generated/common.js +1796 -0
  434. package/dist/visualizer/protobuf.generated/common.js.map +1 -0
  435. package/dist/visualizer/runtime-config.d.ts +2 -0
  436. package/dist/visualizer/runtime-config.d.ts.map +1 -0
  437. package/dist/visualizer/runtime-config.js +5 -0
  438. package/dist/visualizer/runtime-config.js.map +1 -0
  439. package/dist/visualizer/utils/artificial-worker.d.ts +10 -0
  440. package/dist/visualizer/utils/artificial-worker.d.ts.map +1 -0
  441. package/dist/visualizer/utils/artificial-worker.js +31 -0
  442. package/dist/visualizer/utils/artificial-worker.js.map +1 -0
  443. package/dist/visualizer/utils/async.d.ts +3 -0
  444. package/dist/visualizer/utils/async.d.ts.map +1 -0
  445. package/dist/visualizer/utils/async.js +35 -0
  446. package/dist/visualizer/utils/async.js.map +1 -0
  447. package/dist/visualizer/utils/browser-storage.d.ts +3 -0
  448. package/dist/visualizer/utils/browser-storage.d.ts.map +1 -0
  449. package/dist/visualizer/utils/browser-storage.js +16 -0
  450. package/dist/visualizer/utils/browser-storage.js.map +1 -0
  451. package/dist/visualizer/utils/callback-manager.d.ts +7 -0
  452. package/dist/visualizer/utils/callback-manager.d.ts.map +1 -0
  453. package/dist/visualizer/utils/callback-manager.js +21 -0
  454. package/dist/visualizer/utils/callback-manager.js.map +1 -0
  455. package/dist/visualizer/utils/comlink-wrap.d.ts +7 -0
  456. package/dist/visualizer/utils/comlink-wrap.d.ts.map +1 -0
  457. package/dist/visualizer/utils/comlink-wrap.js +15 -0
  458. package/dist/visualizer/utils/comlink-wrap.js.map +1 -0
  459. package/dist/visualizer/utils/compatibility.d.ts +2 -0
  460. package/dist/visualizer/utils/compatibility.d.ts.map +1 -0
  461. package/dist/visualizer/utils/compatibility.js +19 -0
  462. package/dist/visualizer/utils/compatibility.js.map +1 -0
  463. package/dist/visualizer/utils/config-store.d.ts +10 -0
  464. package/dist/visualizer/utils/config-store.d.ts.map +1 -0
  465. package/dist/visualizer/utils/config-store.js +22 -0
  466. package/dist/visualizer/utils/config-store.js.map +1 -0
  467. package/dist/visualizer/utils/encoding.d.ts +4 -0
  468. package/dist/visualizer/utils/encoding.d.ts.map +1 -0
  469. package/dist/visualizer/utils/encoding.js +23 -0
  470. package/dist/visualizer/utils/encoding.js.map +1 -0
  471. package/dist/visualizer/utils/error.d.ts +20 -0
  472. package/dist/visualizer/utils/error.d.ts.map +1 -0
  473. package/dist/visualizer/utils/error.js +79 -0
  474. package/dist/visualizer/utils/error.js.map +1 -0
  475. package/dist/visualizer/utils/estimate-object-size.d.ts +2 -0
  476. package/dist/visualizer/utils/estimate-object-size.d.ts.map +1 -0
  477. package/dist/visualizer/utils/estimate-object-size.js +60 -0
  478. package/dist/visualizer/utils/estimate-object-size.js.map +1 -0
  479. package/dist/visualizer/utils/frame-store.d.ts +13 -0
  480. package/dist/visualizer/utils/frame-store.d.ts.map +1 -0
  481. package/dist/visualizer/utils/frame-store.js +43 -0
  482. package/dist/visualizer/utils/frame-store.js.map +1 -0
  483. package/dist/visualizer/utils/imu-manager.d.ts +13 -0
  484. package/dist/visualizer/utils/imu-manager.d.ts.map +1 -0
  485. package/dist/visualizer/utils/imu-manager.js +36 -0
  486. package/dist/visualizer/utils/imu-manager.js.map +1 -0
  487. package/dist/visualizer/utils/logger.d.ts +13 -0
  488. package/dist/visualizer/utils/logger.d.ts.map +1 -0
  489. package/dist/visualizer/utils/logger.js +47 -0
  490. package/dist/visualizer/utils/logger.js.map +1 -0
  491. package/dist/visualizer/utils/metrics-manager.d.ts +33 -0
  492. package/dist/visualizer/utils/metrics-manager.d.ts.map +1 -0
  493. package/dist/visualizer/utils/metrics-manager.js +113 -0
  494. package/dist/visualizer/utils/metrics-manager.js.map +1 -0
  495. package/dist/visualizer/utils/player-types.d.ts +65 -0
  496. package/dist/visualizer/utils/player-types.d.ts.map +1 -0
  497. package/dist/visualizer/utils/player-types.js +22 -0
  498. package/dist/visualizer/utils/player-types.js.map +1 -0
  499. package/dist/visualizer/utils/poitcloud-sync.d.ts +13 -0
  500. package/dist/visualizer/utils/poitcloud-sync.d.ts.map +1 -0
  501. package/dist/visualizer/utils/poitcloud-sync.js +95 -0
  502. package/dist/visualizer/utils/poitcloud-sync.js.map +1 -0
  503. package/dist/visualizer/utils/runtime-config.d.ts +23 -0
  504. package/dist/visualizer/utils/runtime-config.d.ts.map +1 -0
  505. package/dist/visualizer/utils/runtime-config.js +76 -0
  506. package/dist/visualizer/utils/runtime-config.js.map +1 -0
  507. package/dist/visualizer/utils/segmentation-colors.d.ts +9 -0
  508. package/dist/visualizer/utils/segmentation-colors.d.ts.map +1 -0
  509. package/dist/visualizer/utils/segmentation-colors.js +42 -0
  510. package/dist/visualizer/utils/segmentation-colors.js.map +1 -0
  511. package/dist/visualizer/utils/time.d.ts +7 -0
  512. package/dist/visualizer/utils/time.d.ts.map +1 -0
  513. package/dist/visualizer/utils/time.js +24 -0
  514. package/dist/visualizer/utils/time.js.map +1 -0
  515. package/dist/visualizer/utils/use-theme-mode.d.ts +3 -0
  516. package/dist/visualizer/utils/use-theme-mode.d.ts.map +1 -0
  517. package/dist/visualizer/utils/use-theme-mode.js +71 -0
  518. package/dist/visualizer/utils/use-theme-mode.js.map +1 -0
  519. package/package.json +33 -8
  520. package/protobuf-gen.sh +87 -0
  521. package/protobuf-gen.win.ps1 +130 -0
  522. package/scripts/browser-decoder-fixtures.html +54 -0
  523. package/scripts/fixtures.vite.config.mjs +30 -0
  524. package/scripts/run-decoder-fixtures.mjs +45 -0
@@ -0,0 +1,969 @@
1
+ # REFACTOR_HANDOFF.md
2
+
3
+ ## Update Protocol
4
+
5
+ Every agent must update this file after each completed logical change set and before ending a session.
6
+
7
+ Required fields to keep current:
8
+
9
+ - branch
10
+ - latest commit for the completed checkpoint
11
+ - what changed
12
+ - validation run
13
+ - known open risks
14
+ - exact next task
15
+
16
+ ## Current Status
17
+
18
+ - Date: 2026-05-23
19
+ - Branch: `performance/hitching-improvements`
20
+ - Phase: Phase 5 package/runtime cleanup in progress
21
+ - Latest completed checkpoint: remove unsafe compressed-input shedding from H.264/H.265 live decode
22
+ - Latest commit for this checkpoint: pending commit for the current checkpoint
23
+
24
+ ## What Was Completed
25
+
26
+ - `trace7.json` changed the direction again: after transport batching and latest-frame coalescing, the dominant remaining app-side cost was still in the shared image presentation path rather than in app-specific React layout.
27
+ - The meaningful app-side spikes were still repeated `raw-image-decoder.worker` callbacks around 20-35 ms, while both raw and encoded streams eventually converged on the same `foxglove.RawImage` panel path.
28
+ - Reworked `src/panels/image/ImageCanvasRenderer.tsx` so common live formats no longer go through the CPU raw-image decode worker before display:
29
+ - added a dedicated WebGL canvas path for `nv12`, `yuv420p` / `I420`, `rgb8`, `bgr8i`, `rgba8`, `bgra8`, and `mono8`
30
+ - kept the previous worker-decoder path as fallback for unsupported formats such as Bayer, `mono16`, and odd-stride cases
31
+ - kept annotation overlay rendering on the separate 2D overlay canvas
32
+ - kept latest-frame-only behavior and rAF-gated draw scheduling around the new presenter
33
+ - Added `src/panels/image/webgl-image-renderer.ts` to upload planar or packed image buffers directly to WebGL textures and do color conversion in shaders instead of in `raw-image-decoder.worker`.
34
+ - This specifically removes the hottest repeated CPU loop for the common shared path used by both raw camera streams and encoded H.264/H.265 frames once they are represented as `foxglove.RawImage`.
35
+ - User retest after this change reported that raw-stream hitching is now minimal instead of obvious/periodic, which is the strongest manual confirmation so far that the shared image presentation path was a real part of the problem.
36
+ - Exact files changed for this checkpoint:
37
+ - `src/panels/image/ImageCanvasRenderer.tsx`
38
+ - `src/panels/image/webgl-image-renderer.ts`
39
+ - Follow-up browser findings changed the working diagnosis: the hitch is not encoded-only. Raw streams still lag periodically, and raw gets materially worse when H.264 is enabled beside it.
40
+ - That points to shared decode/presentation contention plus hot-path CPU/GC churn, not only inter-frame codec behavior.
41
+ - Reduced cross-topic contention in `src/messaging/message-handler.ts` by giving image topics dedicated deserialization workers while keeping non-image traffic on the bounded shared pool.
42
+ - Reduced stale panel-side decode work in `src/panels/image/ImageCanvasRenderer.tsx` by making raw-image conversion single-flight latest-frame-only instead of continuing to decode superseded frames.
43
+ - Removed deep `estimateObjectSize()` walks from hot decode outputs where the exact payload byte size is already known:
44
+ - `src/messaging/deserialization/video/color.ts`
45
+ - `src/messaging/deserialization/video/depth.ts`
46
+ - `src/messaging/deserialization/video/depth-to-pointcloud.ts`
47
+ - `src/messaging/deserialization/video/rgbd-to-pointcloud.ts`
48
+ - `src/messaging/deserialization/video/mono.ts`
49
+ - `src/messaging/deserialization/pointcloud/point-cloud.ts`
50
+ - `src/connection/foxglove-connection.ts`
51
+ - Added `getKnownMessageSizeInBytes()` in `src/messaging/message-event.ts` so the connection layer can avoid recursive size estimation for typed-array-backed messages even on fallback paths.
52
+ - Reduced RAW16 decode copies from two full-frame clones to one by cloning the depth-preview buffer up front in `src/messaging/decode-core.ts` and reusing the original decoded bytes for the point-cloud sync artifact in `src/messaging/deserialization/video/depth-to-pointcloud.ts`.
53
+ - Validation for this checkpoint:
54
+ - `npm run build:visualizer-protobuf`
55
+ - `npm run build:common`
56
+ - `npm run build:visualizer`
57
+ - `npm run build:viewer`
58
+ - Root cause identified for the recurring encoded-stream hitch shared by `packages/visualizer` and `packages/depthai-viewer/frontend`:
59
+ arbitrary compressed H.264/H.265 frames were being dropped whenever `VideoDecoder.decodeQueueSize >= 3`.
60
+ - That input-drop policy lived in:
61
+ - `src/messaging/deserialization/video/h264.ts`
62
+ - `src/messaging/deserialization/video/h265.ts`
63
+ - For inter-frame codecs this is unsafe because losing compressed delta/reference frames can stall visible output until the next keyframe, which matches the reported roughly-5-second cadence.
64
+ - Removed compressed-input shedding from the live H.264/H.265 decode path in:
65
+ - `src/messaging/deserialization/video/h264.ts`
66
+ - `src/messaging/deserialization/video/h265.ts`
67
+ - Current behavior now keeps the safer decoded-output coalescing only: `queuedOutputFrame` replacement still keeps only the latest decoded frame when output processing is behind, but compressed H.264/H.265 chunks are no longer dropped before decode based on `VideoDecoder.decodeQueueSize`.
68
+ - This change was prompted by visible browser artifacting and stale macroblocks during live playback, which are more consistent with missing inter-frame references than with the native `renderableBitmap` presentation fast path.
69
+ - Added opt-in diagnostics behind runtime query params `?streamDiagnostics=1`, `?visualizerDiagnostics=1`, or `?diagnostics=1`.
70
+ - Added new shared diagnostics helper `src/messaging/stream-diagnostics.ts` and instrumented:
71
+ - encoded ingress cadence / payload size / queue depth
72
+ - backpressure observations at decoder queue pressure
73
+ - decoded-output replacement count
74
+ - worker-side decode-to-output latency using worker-local `performance.now()`
75
+ - image render cadence / long render frames in `src/panels/image/ImageCanvasRenderer.tsx`
76
+ - Extended runtime config bootstrap in `src/utils/runtime-config.ts` so diagnostics can be enabled without app-specific code changes.
77
+ - Exact files changed for this checkpoint:
78
+ - `src/messaging/deserialization/video/h264.ts`
79
+ - `src/messaging/deserialization/video/h265.ts`
80
+ - `src/messaging/stream-diagnostics.ts`
81
+ - `src/panels/image/ImageCanvasRenderer.tsx`
82
+ - `src/utils/runtime-config.ts`
83
+ - Updated `src/panels/pointcloud/PointCloudCanvasRenderer.tsx` so the standalone point-cloud renderer always clears to a white background instead of switching between theme-dependent dark/light colors.
84
+ - Stabilized encoded image delivery end-to-end by keeping live topic subscriptions stable, preserving FIFO ordering for encoded-capable image topics (`encodedFrame` and encoded `imageFrame`), and surfacing decode-path failures instead of silently dropping frames.
85
+ - Hardened the encoded video decode pipeline by treating `FrameType.UNKNOWN` as a recoverable keyframe case, adding native-to-I420 fallback when `createImageBitmap(frame)` fails, suppressing the recoverable initial H.264/H.265 keyframe error until a usable keyframe arrives, and removing the internal double-transfer that was causing detached-buffer failures on encoded streams.
86
+ - Fixed raw/depth image ownership and layout issues by honoring the actual raw image stride for formats like `BGR888i`, and cloning `RAW16` buffers where depth preview and point-cloud sync artifacts share the same source bytes so depth previews no longer lose access to their data.
87
+ - Removed the temporary encoded-stream debugging/instrumentation that was added during investigation, including cross-thread debug plumbing and decode-path metadata that was no longer needed once the stream issues were resolved.
88
+ - Added focused validation for this work by extending `src/messaging/decoder-fixtures.ts` with a stride-backed `BGR888i` case, and kept macOS protobuf generation working via the portable `sed` handling in `protobuf-gen.sh`.
89
+ - Fixed `src/components/Panel.tsx` so annotation-disabled panels no longer trigger a self-sustaining render loop.
90
+ - Replaced inline `[]` default props for `annotationTopics` / `extraAnnotationTopics` with stable shared empty-array defaults.
91
+ - Changed the detections effect to avoid calling `setDetections()` when the computed detections array is already unchanged.
92
+ - This directly addresses the remaining React production error `#185` on `PointCloudPanel`, because that panel sets `disableAnnotations` and previously hit `setDetections([])` on every render through unstable effect dependencies.
93
+ - Fixed the local error-boundary reset behavior so it no longer compares `children` identity on every update.
94
+ - Added an explicit `resetKey` prop to `src/components/ErrorBoundary.tsx` and switched `src/components/Panel.tsx` to reset the boundary only when the stable panel topic changes.
95
+ - This prevents a persistent render exception from turning into a `Maximum update depth exceeded` loop in production (`Minified React error #185`) while preserving deliberate boundary reset behavior for panel swaps.
96
+ - Removed `src/protobuf.generated/*.ts` from the git index so generated protobuf output is no longer tracked by the repository.
97
+ - Removed `src/output.css` from git tracking and added an explicit `.gitignore` entry because Tailwind rebuilds that file locally.
98
+ - Confirmed no extra protobuf ignore rule was needed because `**/protobuf.generated` was already ignored; the issue there was legacy tracked files, not missing ignore coverage.
99
+ - Fixed `protobuf-gen.sh` so `protoc` resolves `protoc-gen-ts_proto` from the repository root instead of using the stale `../../node_modules/.bin/...` path after `pushd ./~proto`.
100
+ - Added an explicit executable check for the resolved `ts-proto` plugin and a clearer failure message when dependencies are not installed.
101
+ - Created `AGENTS.md` with architecture findings, compatibility constraints, and agent workflow rules.
102
+ - Created `REFACTOR_PLAN.md` with phased refactor plan.
103
+ - Created `REFACTOR_HANDOFF.md` as the running handoff ledger.
104
+ - Extracted shared decoder orchestration from `src/messaging/deserialization.worker.ts` into `src/messaging/decode-core.ts`.
105
+ - Added `src/messaging/decoder-harness.ts` so future fixture tests can invoke decoder logic directly without going through the worker entrypoint.
106
+ - Kept `deserialization.worker.ts` as a thin Comlink wrapper over the extracted decode core.
107
+ - Added `src/messaging/decoder-fixtures.ts` with built-in synthetic fixture cases for:
108
+ - raw color image frames
109
+ - IMU data
110
+ - colored point clouds
111
+ - image detections
112
+ - custom image annotations
113
+ - Added focused assertions around current emitted behavior rather than only raw deep snapshots.
114
+ - Added local decoder runtime primitives so the deserialization subtree no longer imports Foxglove runtime helpers for:
115
+ - message event typing
116
+ - parse/time helpers
117
+ - object size estimation
118
+ - Updated the decoder subtree to consume those local primitives instead of `@foxglove/studio-base` runtime modules.
119
+ - Made the depth worker pool lazy so importing decoder modules no longer immediately requires `Worker`.
120
+ - Added a repository-native fixture entrypoint:
121
+ - `scripts/run-decoder-fixtures.mjs`
122
+ - `yarn fixtures:decode`
123
+ - Replaced the root package-manager workflow with npm:
124
+ - added `package-lock.json`
125
+ - added `.npmrc` with `legacy-peer-deps=true` so the current dependency graph resolves under npm
126
+ - removed `.yarn/`, `.yarnrc.yml`, and `yarn.lock`
127
+ - updated `package.json` scripts and package-manager metadata to npm
128
+ - updated active docs and agent notes to use npm commands
129
+ - Replaced the copied formatter/linter setup with a repo-local Biome workflow:
130
+ - added `@biomejs/biome`
131
+ - added a package-local `biome.json` tuned for this repo’s JS/TS/JSON scope
132
+ - excluded generated Tailwind output and the Tailwind input stylesheet from Biome checks
133
+ - disabled Biome rules that were a poor fit for the current React/canvas patterns:
134
+ - `useExhaustiveDependencies`
135
+ - `noStaticElementInteractions`
136
+ - `useKeyWithClickEvents`
137
+ - `noAccumulatingSpread`
138
+ - removed the old legacy lint/format config files and compatibility tsconfig
139
+ - updated npm scripts to:
140
+ - `npm run lint`
141
+ - `npm run lint:fix`
142
+ - `npm run format`
143
+ - updated GitHub workflows to use npm and run Biome instead of the old Yarn/legacy lint flow
144
+ - applied one repository-wide Biome write pass and fixed the remaining manual diagnostics so `biome check` is now clean
145
+ - Added `lefthook` as the repo hook manager and configured [lefthook.yml](/home/davidfencl/Documents/Work/depthai-visualizer-lib/lefthook.yml) with a `pre-commit` hook that runs:
146
+ - `npx biome check --write --no-errors-on-unmatched --files-ignore-unknown=true {staged_files}`
147
+ - with `stage_fixed: true` so rewritten staged files are re-added automatically
148
+ - Added `prepare: "lefthook install"` to `package.json` so hook installation happens automatically on `npm install`
149
+ - Removed the dead Jest toolchain from package metadata:
150
+ - `jest`
151
+ - `jest-environment-jsdom`
152
+ - `@types/jest`
153
+ - Regenerated `package-lock.json` without the Jest dependency tree. The removal required `npm install --ignore-scripts` in the sandbox because the repo-level `prepare` hook tries to rewrite `.git/hooks`.
154
+ - Pruned additional dead package/tooling dependencies that are no longer referenced by source, scripts, CI, or build config:
155
+ - `@actions/core`
156
+ - `@actions/exec`
157
+ - `@actions/tool-cache`
158
+ - `@octokit/rest`
159
+ - `@babel/plugin-proposal-explicit-resource-management`
160
+ - `@types/surma__rollup-plugin-off-main-thread`
161
+ - `@wasm-tool/rollup-plugin-rust`
162
+ - `babel-plugin-transform-import-meta`
163
+ - `cross-env`
164
+ - `depcheck`
165
+ - `license-checker`
166
+ - `rimraf`
167
+ - `semver`
168
+ - `ts-unused-exports`
169
+ - `webpack`
170
+ - `webpack-cli`
171
+ - `webpack-dev-server`
172
+ - `webpack-hot-middleware`
173
+ - Regenerated `package-lock.json` after that prune with `npm install --ignore-scripts` to avoid sandbox-only `prepare` hook failures while still pruning the resolved tree correctly.
174
+ - Raised the declared Node.js engine floor in `package.json` from `>=16` to `>=22`.
175
+ - Aligned the pull-request GitHub workflow to Node 22 explicitly by updating `.github/workflows/pull-request.yml` to `actions/setup-node@v4` with `node-version: "22"`.
176
+ - Bumped package version metadata from `3.1.14` to `4.0.0-rc.1` in:
177
+ - `package.json`
178
+ - `package-lock.json`
179
+ - Refreshed a conservative same-major dependency slice across runtime and build tooling, including current-version updates for:
180
+ - `@bufbuild/protobuf`
181
+ - `@luxonis/ui-components`
182
+ - `@luxonis/ui-utils`
183
+ - `comlink`
184
+ - legacy formatter bridge packages
185
+ - `react-icons`
186
+ - `react-syntax-highlighter`
187
+ - `uuidv7`
188
+ - `react` / `react-dom`
189
+ - `@babel/core`
190
+ - `@babel/plugin-proposal-explicit-resource-management`
191
+ - `@babel/preset-env`
192
+ - `@babel/preset-typescript`
193
+ - `@tailwindcss/cli`
194
+ - `@types/dom-webcodecs`
195
+ - `@types/react`
196
+ - `@webgpu/types`
197
+ - `babel-plugin-transform-import-meta`
198
+ - legacy lint integration packages
199
+ - `rollup`
200
+ - `rollup-plugin-string-import`
201
+ - `semver`
202
+ - `tailwindcss`
203
+ - `ts-proto`
204
+ - `tslib`
205
+ - `webpack`
206
+ - `webpack-hot-middleware`
207
+ - The refreshed `@types/dom-webcodecs` package exposed a compile-time MJPEG typing regression.
208
+ - Fixed that by:
209
+ - making `src/messaging/deserialization/video/mjpeg.ts` use an explicit `ImageDecoder` constructor lookup instead of relying on an ambient global symbol declaration
210
+ - making the MJPEG payload shape explicit across native and i420 branches
211
+ - correcting `src/utils/compatibility.ts` so `ensureWebCodecsSupported()` actually checks the real WebCodecs constructor on `globalThis`
212
+ - Removed the last direct MUI dependency from source code by replacing `useTheme()` in `src/panels/pointcloud/PointCloudCanvasRenderer.tsx` with a local browser theme-mode hook:
213
+ - added `src/utils/use-theme-mode.ts`
214
+ - the point-cloud renderer now tracks theme changes through common DOM theme attributes/classes and `prefers-color-scheme`
215
+ - Removed direct package/runtime dependency declarations for:
216
+ - `@mui/icons-material`
217
+ - `@mui/material`
218
+ - `@mui/system`
219
+ - `@emotion/react`
220
+ - `@emotion/styled`
221
+ - Removed the corresponding stale Rollup externals from `rollup.config.js`.
222
+ - Updated `three` from `0.156.1` to `0.184.0`.
223
+ - Kept explicit `@types/three`, but updated it to the matching `0.184.0` line after verifying that the current TypeScript/module-resolution setup still needs it for clean type resolution of both `three` and `three/examples/jsm/controls/OrbitControls.js`.
224
+ - Relaxed a few floating-point fixture tolerances to match actual emitted values in runnable execution.
225
+ - Expanded Node-safe fixture coverage with:
226
+ - uncolored point clouds
227
+ - spatial image detections
228
+ - Recorded the browser-only runtime constraint in `AGENTS.md` and `REFACTOR_PLAN.md` so future agents do not overfit validation to Node.
229
+ - Added a browser-runtime fixture suite and entrypoint for worker-backed decoder paths:
230
+ - `src/messaging/browser-decoder-fixtures.ts`
231
+ - `src/browser-decoder-fixtures-entry.ts`
232
+ - `scripts/browser-decoder-fixtures.html`
233
+ - Added browser fixture coverage for:
234
+ - raw depth preview plus sync point-cloud artifact
235
+ - RGBD depth preview plus colored point-cloud emission
236
+ - Replaced one-worker-per-topic decode fanout with a bounded shared decoder worker pool in `src/messaging/message-handler.ts`.
237
+ - Switched decode worker dispatch to explicit transferable buffer handoff instead of plain Comlink value passing for the message payload.
238
+ - Removed per-message `ConfigStore` serialization across Comlink by pushing connection config into decoder workers once during worker initialization.
239
+ - Reduced repeated decode-settings parsing by caching raw `localStorage` values and only re-parsing when same-tab values actually change.
240
+ - Removed O(n) point-cloud sync cleanup in `src/utils/poitcloud-sync.ts` by replacing repeated array shifting with indexed queue compaction.
241
+ - Removed repeated `localStorage` parsing on the legacy point-cloud conversion path by caching neural camera intrinsics in `src/connection/foxglove-connection.ts`.
242
+ - Removed repeated `localStorage` reads from `DepthToPointcloudWorkerPool` batch dispatch and replaced processed-frame queue shifting with indexed compaction in `src/messaging/deserialization/pointcloud/poitcloudPoolManager.ts`.
243
+ - Switched the point-cloud worker contract to explicit transferable typed-array handoff on both input and output in:
244
+ - `src/messaging/deserialization/pointcloud/pointcloudFromDepth.worker.ts`
245
+ - `src/messaging/deserialization/pointcloud/poitcloudPoolManager.ts`
246
+ - `src/messaging/deserialization/video/rgbd-to-pointcloud.ts`
247
+ - Added local helper modules:
248
+ - `src/utils/async.ts`
249
+ - `src/utils/time.ts`
250
+ - Updated `src/connection/foxglove-connection.ts` to use local debounce/time/object-size helpers and local message-event typing instead of Foxglove helper imports.
251
+ - Updated `src/utils/frame-store.ts` to store local `VisualizerMessageEvent` values instead of Foxglove Studio event types.
252
+ - Added `src/utils/comlink-wrap.ts` as a local Comlink worker wrapper.
253
+ - Updated:
254
+ - `src/messaging/message-handler.ts`
255
+ - `src/messaging/deserialization.worker.ts`
256
+ - `src/messaging/deserialization/pointcloud/poitcloudPoolManager.ts`
257
+ to use the local Comlink wrapper and local `VisualizerMessageEvent` typing instead of Foxglove worker/event helpers.
258
+ - Added local `fromMicros()` to `src/utils/time.ts`.
259
+ - Updated:
260
+ - `src/messaging/deserialization/video/h264.ts`
261
+ - `src/messaging/deserialization/video/h265.ts`
262
+ to use the local time helper instead of `@foxglove/rostime`.
263
+ - Added `src/utils/player-types.ts` as a local player-state/type surface for the internal connection/context layer.
264
+ - Updated:
265
+ - `src/connection/foxglove-connection.ts`
266
+ - `src/connection/connection.ts`
267
+ - `src/context/VisualizerContext.tsx`
268
+ - `src/context/MessagePipelineProvider.tsx`
269
+ to use local player types internally, with explicit adaptation at the Foxglove `MessagePipelineProvider` boundary.
270
+ - Replaced the Foxglove `MessagePipeline` implementation with a Luxonis-owned local pipeline store and hooks:
271
+ - `src/context/message-pipeline-types.ts`
272
+ - `src/context/message-pipeline-order-tracker.ts`
273
+ - `src/context/message-pipeline-store.ts`
274
+ - `src/context/pause-frame.ts`
275
+ - Updated `src/context/MessagePipelineProvider.tsx` to use the local store while still exposing a Foxglove-compatible context shape to legacy panels through `ContextInternal`.
276
+ - Updated `src/context/VisualizerContext.tsx` and `src/messaging/utils.ts` to use the local pipeline hooks instead of Foxglove `useMessagePipeline` / `useMessageReducer`.
277
+ - Added local panel-shell components:
278
+ - `src/components/EmptyState.tsx`
279
+ - `src/components/ErrorBoundary.tsx`
280
+ - `src/components/RemountOnValueChange.tsx`
281
+ - Updated `src/components/Panel.tsx` to use those local components instead of Foxglove UI helpers.
282
+ - Updated `src/components/PanelLayout.tsx` to use a local flex layout instead of Foxglove `Stack`.
283
+ - Updated `src/context/VisualizerContext.tsx` to use the local `ErrorBoundary`.
284
+ - Added local panel/runtime boundary helpers:
285
+ - `src/panels/panel-renderer.ts`
286
+ - `src/panels/pointcloud-camera.ts`
287
+ - Updated `src/components/Panel.tsx`, `src/panels/ImagePanel.tsx`, and `src/panels/PointCloudPanel.tsx` so public panel props no longer import the Foxglove `Renderer` type.
288
+ - Updated `src/panels/PointCloudPanel.tsx` to use local point-cloud camera defaults instead of importing them from Foxglove `ThreeDeeRender`.
289
+ - Updated `src/context/MessagePipelineProvider.tsx` to use local player/problem types only; the remaining Foxglove dependency there is now just `ContextInternal`.
290
+ - Added a local browser-only image rendering stack under `src/panels/image/`:
291
+ - `raw-image-decoder.ts`
292
+ - `raw-image-decoder.worker.ts`
293
+ - `worker-image-decoder.ts`
294
+ - `annotation-overlay.ts`
295
+ - `ImageCanvasRenderer.tsx`
296
+ - Replaced the Foxglove `Image` panel usage in `src/panels/ImagePanel.tsx` with a local canvas-based image host.
297
+ - Added a browser-native encoded-video presentation fast path:
298
+ - `src/messaging/deserialization/video/h264.ts`
299
+ - `src/messaging/deserialization/video/h265.ts`
300
+ - `src/messaging/message-event.ts`
301
+ - `src/panels/image/ImageCanvasRenderer.tsx`
302
+ - H.264/H.265 decode workers now attach a transferred `ImageBitmap` to emitted `foxglove.RawImage` events for normal image topics while keeping the raw-image payload fields intact.
303
+ - The local image panel now renders those transferred bitmaps directly instead of sending encoded-video-origin raw images through the second worker-based RGBA decode step.
304
+ - Bitmap lifetime is now explicitly closed on replacement and unmount in `ImageCanvasRenderer.tsx` to avoid leaks during high-rate streams.
305
+ - Encoded H.264/H.265 worker callbacks now transfer the raw payload `ArrayBuffer` alongside any attached `ImageBitmap` instead of structured-cloning the raw image bytes back to the main thread.
306
+ - `src/connection/foxglove-connection.ts` now reuses decoder-supplied `event.sizeInBytes` when present instead of re-running `estimateObjectSize(event.message)` on every decoded frame before enqueueing it into the local pipeline.
307
+ - Removed the legacy per-player-state renderDone/pauseFrame synchronization gate from:
308
+ - `src/context/MessagePipelineProvider.tsx`
309
+ - `src/context/message-pipeline-store.ts`
310
+ - The local pipeline now dispatches player-state updates directly instead of creating a timeout/promise handshake for every frame even though no current code path uses `pauseFrame()`.
311
+ - Added `stripRenderableBitmapFromEvent()` in `src/messaging/message-event.ts`.
312
+ - `src/utils/frame-store.ts` and `src/context/message-pipeline-store.ts` now strip `renderableBitmap` before storing decoded image events in long-lived caches.
313
+ - Live subscribers still receive the browser-native bitmap fast path on current messages, but main-thread caches no longer retain `ImageBitmap` objects across frames.
314
+ - Added `createCachedEventSnapshot()` in `src/messaging/message-event.ts`.
315
+ - `FrameStore` and the pipeline `lastMessageEventByTopic` cache now also replace `foxglove.RawImage.message.data` with an empty `Uint8Array` in cached snapshots, so old video-frame buffers are not retained between updates.
316
+ - Browser trace analysis of `trace1.json` showed two renderer main-thread spikes about 5 seconds apart. The spikes resolved to repeated `clearInterval` / `setInterval` churn and React work around the local panel metrics hooks.
317
+ - Updated:
318
+ - `src/components/measure-event-loop-delay.tsx`
319
+ - `src/components/measure-render-delay.tsx`
320
+ - Both hooks now keep one stable interval instead of recreating timers on every state update.
321
+ - `createRenderDelaySampler()` also no longer allocates and clears a growing `frameDelays` array every frame; it now tracks running count/sum in refs.
322
+ - Browser trace analysis of `trace2.json` still showed periodic main-thread spikes and repeated timer/layout activity in the toolbar/metrics path after the first hook cleanup.
323
+ - Added:
324
+ - `src/components/shared-interval.ts`
325
+ - `src/components/use-element-width.ts`
326
+ - Updated:
327
+ - `src/components/PanelToolbar.tsx`
328
+ - `src/components/measure-event-loop-delay.tsx`
329
+ - Panel toolbar metrics and connection metric polling now share one page-level interval instead of creating per-panel timers.
330
+ - Frontend delay sampling is now a shared `useSyncExternalStore`-backed sampler, which restores the FE delay readout without reintroducing timer churn per panel.
331
+ - Toolbar compact/full and resolution behavior now use `ResizeObserver` width tracking instead of reading `offsetWidth`/`clientWidth` inside render-driven effects.
332
+ - Browser trace analysis of `trace3.json` still showed the same periodic main-thread `FunctionCall` spikes at the same bundle callsite as `trace2.json`, so the underlying hitch was unchanged by the toolbar polling cleanup.
333
+ - The active working tree also contained an uncommitted `requestAnimationFrame` rewrite of `FoxgloveConnection.emitState()`. That change was not part of any checkpoint and was removed from the runtime path before further hitch analysis.
334
+ - Updated `src/components/measure-event-loop-delay.tsx` again so the FE delay readout now samples from the shared 500ms UI tick directly, instead of relying on the earlier `useSyncExternalStore` sampler variant.
335
+ - Removed the legacy `MessageOrderTracker` pipeline layer entirely:
336
+ - deleted `src/context/message-pipeline-order-tracker.ts`
337
+ - simplified `src/context/MessagePipelineProvider.tsx` so player-state updates are forwarded directly into the local pipeline store without per-batch message-order/drift scans or warning timers
338
+ - Clamped the frontend delay metric to non-negative values in `src/components/measure-event-loop-delay.tsx` so scheduling jitter no longer reports impossible negative delays.
339
+ - Removed the Frontend Delay metric from `src/components/PanelToolbar.tsx` for now so it no longer adds diagnostic noise while the H.264 hitch investigation continues.
340
+ - Reduced per-frame main-thread allocation pressure in the player-state and cache path:
341
+ - `src/messaging/message-event.ts` now returns original event/message references when no `renderableBitmap` stripping is needed, instead of cloning every cached event unconditionally
342
+ - cached raw-image events no longer allocate synthetic empty `Uint8Array` payloads
343
+ - `src/connection/foxglove-connection.ts` now caches topic definitions incrementally with `trackTopic()` instead of rebuilding `Object.values(this.topics)` on every emit
344
+ - `FoxgloveConnection.emitState()` now reuses shared empty `progress`, `topicStats`, and `datatypes` containers instead of allocating fresh ones on every player-state update
345
+ - Narrowed the live frame payload that flows through the central pipeline store:
346
+ - `src/context/MessagePipelineProvider.tsx` now strips live `activeData.messages` out of the public `PlayerState` and forwards those events separately to the store
347
+ - `src/context/message-pipeline-store.ts` now builds `messageEventsBySubscriberId` from that separate internal message payload instead of reading live frame arrays back off public `playerState`
348
+ - Result: panels still receive current frame events through `messageEventsBySubscriberId`, but the broader `playerState` object no longer carries every decoded frame buffer through the whole Zustand/React surface.
349
+ - Reworked the image panel hot path so live image frames no longer drive React state updates:
350
+ - `src/context/MessagePipelineProvider.tsx` now exposes the local store API
351
+ - `src/messaging/utils.ts` now provides `useMessageSubscription()` for imperative subscriber callbacks without rerendering the component on every message batch
352
+ - `src/panels/image/ImageCanvasRenderer.tsx` now handles image-frame and annotation messages through refs plus direct canvas scheduling instead of `useMessageReducer()` state churn
353
+ - decoded images/bitmaps are stored in refs and drawn via scheduled canvas work, while React state is only used for coarse UI state like resize and “waiting for frames”
354
+ - Verified that `renderDelay` is dead in the current UI:
355
+ - `ImagePanel` and `PointCloudPanel` computed it via `createRenderDelaySampler()`
356
+ - `Panel` threaded it into `PanelToolbar`
357
+ - `PanelToolbar` typed it but did not read it
358
+ - Removed that dead periodic rerender path:
359
+ - deleted `src/components/measure-render-delay.tsx`
360
+ - removed `createRenderDelaySampler()` usage from `src/panels/ImagePanel.tsx` and `src/panels/PointCloudPanel.tsx`
361
+ - removed `renderDelay` from `src/components/Panel.tsx` and `src/components/PanelToolbar.tsx`
362
+ - Reduced `PanelToolbar` / `PanelToolbarMetrics` shared metrics tick interval from `500ms` to `1000ms` as a low-risk reduction in always-on toolbar churn while preserving visible stats updates.
363
+ - The new image host:
364
+ - subscribes directly to `foxglove.RawImage` and `foxglove.ImageAnnotations` through the local message pipeline
365
+ - decodes browser image frames in a dedicated worker
366
+ - draws images into a canvas with local annotation overlay rendering
367
+ - preserves panel click/cursor callbacks and panel render metrics hooks
368
+ - Fixed a render-loop regression in `src/panels/image/ImageCanvasRenderer.tsx` by memoizing the `topics` array passed into `useMessageReducer`, so the message-pipeline subscription effect no longer re-subscribes on every render.
369
+ - Fixed a second render-loop regression in `src/panels/image/ImageCanvasRenderer.tsx` by removing unstable callback props from effect dependencies on the draw/registration path. The image host now keeps the latest callbacks in refs instead of treating parent callback identity changes as redraw triggers.
370
+ - Updated the local image host visuals to use a white background and lighter empty-state text.
371
+ - Fixed `src/panels/image/annotation-overlay.ts` so annotation point types are rendered as discrete points instead of being treated as connected paths. Line list, line strip, and line loop are now handled explicitly by schema type.
372
+ - Fixed image render FPS reporting in `src/panels/image/ImageCanvasRenderer.tsx` so `frameRenderedEvent` is emitted only when a new decoded image revision is presented, not on annotation-only redraws.
373
+ - Updated `AGENTS.md` and `REFACTOR_PLAN.md` to track a real browser-runtime issue: periodic video hitching roughly every 5 seconds on encoded H.264/H.265 streams, currently suspected to involve the encoded-video decode path until profiling proves otherwise.
374
+ - Updated `src/messaging/deserialization/video/h264.ts` and `src/messaging/deserialization/video/h265.ts` to stop marking every `EncodedVideoChunk` as a keyframe when the source is `EncodedFrame`; `I` frames now map to `"key"` and `P/B` frames map to `"delta"`.
375
+ - Replaced the previous hard decoder reset on large decode backlog with bounded frame dropping. When the `VideoDecoder.decodeQueueSize` crosses the new threshold, incoming encoded frames are dropped instead of resetting the decoder and forcing a keyframe reacquire cycle.
376
+ - Kept the fallback `ImgFrame` bitstream path conservative by still treating it as keyframe-only input because that message type does not expose explicit frame-type metadata.
377
+ - Updated the encoded-video output path to use a latest-frame policy while expensive `VideoFrame.copyTo()` / repack work is in progress. H.264/H.265 now serialize output-frame conversion per topic and drop superseded decoded frames instead of allowing async output processing to pile up.
378
+ - Replaced `estimateObjectSize()` on the H.264/H.265 decoded image hot path with direct `Uint8Array.byteLength` accounting.
379
+ - Added a native `NV12` fast path for regular encoded H.264/H.265 image topics. When `VideoDecoder` outputs uncropped `NV12`, the pipeline now emits that buffer directly as `foxglove.RawImage` with stride metadata instead of repacking it to `yuv420p`.
380
+ - Kept RGBD encoded color extraction on the older I420-compatible path by explicitly requesting `outputMode: "i420"` there, so point-cloud generation semantics remain unchanged while normal image streams get the lighter decode path.
381
+ - Updated `src/messaging/deserialization/video/h264.ts` and `src/messaging/deserialization/video/h265.ts` so the normal `outputMode: "native"` path no longer calls `VideoFrame.copyTo()` just to populate `foxglove.RawImage.data`.
382
+ - Regular encoded H.264/H.265 image topics now transfer only `ImageBitmap` plus image metadata to the main thread, while preserving raw-plane extraction on the explicit RGBD `outputMode: "i420"` path.
383
+ - Decoder events on that native path now keep `sizeInBytes` from `VideoFrame.allocationSize()` so throughput metrics still reflect decoded frame weight even though the live raw-image payload is no longer materialized.
384
+ - Analyzed the new 20-second `trace5.json` capture from the simpler Visualizer app with only one H.264 stream active.
385
+ - Trace finding: the hitch still reproduces without consuming-app complexity, and the renderer main thread no longer shows a single 5-second JS spike. Instead, `raw-image-decoder.worker` is still doing roughly 3-5 ms of `HandlePostMessage` / `FunctionCall` work on nearly every frame.
386
+ - That worker activity should have disappeared on the `ImageBitmap` fast path, so the remaining likely bug was the worker-to-main-thread callback transport rather than decode itself.
387
+ - Replaced the decoder worker callback delivery path with an explicit `MessagePort` transfer channel:
388
+ - `src/messaging/deserialization.worker.ts`
389
+ - `src/messaging/message-handler.ts`
390
+ - `src/messaging/message-event.ts`
391
+ - Decoder workers now post decoded events back to the main thread through a dedicated port with explicit transferables for `Uint8Array` payload buffers and `ImageBitmap`.
392
+ - This removes reliance on the previous proxied Comlink callback for decoded-frame delivery, which was the most likely place `renderableBitmap` was being lost before the image panel subscription saw the live message.
393
+ - Analyzed `trace6.json` after the explicit `MessagePort` transport change.
394
+ - Trace finding: the hitch still reproduces, and `raw-image-decoder.worker` remains hot on nearly every H.264 frame. The expensive fallback path therefore still runs in the image panel even after the worker transport change.
395
+ - Added targeted encoded-image diagnostics to log bitmap presence at each hop:
396
+ - `src/messaging/encoded-image-diagnostics.ts`
397
+ - Extended encoded-image diagnostics so `foxglove.RawImage` events can carry:
398
+ - `renderableBitmapExpected`
399
+ - `renderableBitmapModeUsed`
400
+ - `decodePathSource`
401
+ - Annotated decode outputs in `src/messaging/decode-core.ts` and added `src/messaging/decode-path-diagnostics.ts` so live `foxglove.RawImage` events report which deserialization branch produced them.
402
+ - Browser console diagnostics showed the topic labeled `H.264 Stream` is actually arriving through `encodedFrame:JPEG`, with no `renderableBitmap` attached and no H.264/H.265 output-mode metadata present.
403
+ - Updated `src/messaging/deserialization/video/rgbd-to-pointcloud.ts` so encoded RGBD color extraction uses a synthetic decoder topic key (`::rgbd-color-extract`) and explicitly requests planar output for JPEG as well as H.264/H.265.
404
+ - Reworked `src/messaging/deserialization/video/mjpeg.ts` to support two output modes:
405
+ - default `native` mode now emits transferred `ImageBitmap` plus metadata for normal image topics
406
+ - explicit `i420` mode preserves the old planar `yuv420p` extraction path for RGBD point-cloud color input
407
+ - MJPEG decoded events now use transferables for both raw buffers and `ImageBitmap`, matching the encoded H.264/H.265 fast-path contract.
408
+ - Investigated all periodic timers reachable from `lib/src` during normal streaming.
409
+ - Confirmed the only app-owned repeating timers on the renderer main thread were:
410
+ - `src/connection/foxglove-connection.ts` via eager `RateLimiter` construction
411
+ - `src/messaging/rate-limiter.ts` at `1000ms`
412
+ - `src/messaging/event-loop-delay-sampler.ts` at `500ms`
413
+ - Confirmed `PanelToolbar` metrics removal does not affect that path because `FoxgloveConnection` instantiated the polling rate limiter before any panel-specific UI logic ran.
414
+ - Confirmed the current `RateLimiter` implementation was effectively inert:
415
+ - `src/connection/foxglove-connection.ts` kept `rateLimitModCoefficient` at `1` in normal runtime
416
+ - `src/messaging/rate-limiter.ts` never raised `isFlagUp` from its initial `false` state, so the modulo coefficient callback could not transition from `1` to a throttled value
417
+ - Added a local raw-image pixel decoder module for the internal image panel:
418
+ - `src/panels/image/raw-image-pixel-decoders.ts`
419
+ - Updated `src/panels/image/raw-image-decoder.ts` to use the local decoder module instead of `@foxglove/den/image`.
420
+ - Result: `lib/src` no longer imports `@foxglove/den/image`; the remaining `@foxglove/*` imports are now concentrated in the transport/context shell and the legacy point-cloud renderer boundary.
421
+ - Changed the Phase 1 plan direction for localization/bundle size:
422
+ - removed the `PanelLayout` call into Foxglove `initI18n()`
423
+ - added local no-op stubs for `i18next`, `react-i18next`, and `i18next-browser-languagedetector`
424
+ - wired both TypeScript path resolution and Rollup aliasing to those stubs
425
+ - Result: the library no longer bundles real localization runtime packages; UI text on surviving Foxglove-derived surfaces may now fall back to raw translation keys, which is acceptable for this refactor direction.
426
+ - Removed the last direct import of the Foxglove English translation table from the reachable renderer path:
427
+ - `packages/studio-base/src/panels/ThreeDeeRender/t3D.ts` now accepts a plain string key instead of importing `@foxglove/studio-base/i18n/en` for `keyof typeof threeDee`
428
+ - Fixed `lib/protobuf-gen.sh` so the `protobufName` post-processing step is idempotent:
429
+ - existing `export const protobufName = ...` lines are deleted before the name is appended
430
+ - cleaned the currently generated protobuf modules back to one `protobufName` export each
431
+ - Result: `yarn fixtures:decode` and `yarn build` are both usable again after the earlier duplicate-export corruption.
432
+ - Removed the remaining inert rate-limiter logic from `src/connection/foxglove-connection.ts`:
433
+ - deleted `rateLimitModCoefficient`
434
+ - deleted `rateLimitCounter`
435
+ - removed the dominant-message skip branch from `onMessagePacket()`
436
+ - removed `isMessageTypeDominant()`
437
+ - Replaced the imported Foxglove `CurrentLayoutProvider` in `src/context/VisualizerContext.tsx` with a local minimal provider:
438
+ - added `src/context/MinimalCurrentLayoutProvider.tsx`
439
+ - removed the `@foxglove/studio-base/providers/CurrentLayoutProvider` runtime import from the library shell
440
+ - removed `EventsProvider` from the reachable Visualizer shell
441
+ - Result: one heavier Foxglove provider implementation is no longer in the library’s live context path; the current point-cloud/Image panel shell still validates against the slimmer local layout context.
442
+ - Updated `lib/rollup.config.js` so external dependency handling matches package subpaths instead of only exact package ids.
443
+ - Result: the previous unresolved-dependency warning class is gone from `yarn build`; those runtime deps now resolve as intentional externals instead of noisy unresolved imports.
444
+ - Added a targeted Rollup `onwarn` filter for ignored `"use client"` module directives.
445
+ - Result: `yarn build` output is now reduced to the remaining actionable warning classes rather than hundreds of inert third-party module-directive warnings.
446
+ - Result: the connection hot path no longer carries dead per-packet throttling bookkeeping or skip logic that never activated in real runtime.
447
+ - Removed the dead Foxglove font CSS imports from `packages/studio-base/src/components/CssBaseline.tsx`, which eliminates the unresolved `@foxglove/studio-base/styles/assets/*.woff2` warning class from `yarn build`.
448
+ - Converted MUI/theme-only imports in:
449
+ - `packages/theme/src/palette.ts`
450
+ - `packages/theme/src/createMuiTheme.ts`
451
+ - `packages/theme/src/typography.ts`
452
+ to `import type`, which removes the previous Rollup `Missing exports` / `Unused external imports` warnings caused by treating types as runtime imports.
453
+ - Added explicit dependency declarations in `lib/package.json` for modules that the current build reaches transitively through Foxglove/Luxonis UI layers, so the package no longer relies on those as accidental undeclared externals.
454
+ - Added `preventAssignment: true` to the Rollup `replace()` plugin config to clear that plugin warning.
455
+ - Removed the eager `RateLimiter` instantiation from `src/connection/foxglove-connection.ts`.
456
+ - Deleted the now-unused timer-backed modules:
457
+ - `src/messaging/rate-limiter.ts`
458
+ - `src/messaging/event-loop-delay-sampler.ts`
459
+ - Post-change timer inventory for `setInterval()` in `lib/src` is now limited to:
460
+ - `src/components/shared-interval.ts`, which is tied to mounted UI metrics consumers rather than connection startup
461
+ - `src/connection/webrtc/comms-proxy.ts`, which is a 5-minute token refresh path specific to WebRTC comms
462
+ - Analyzed `trace9.json` after the rate-limiter removal on a one-panel H.264 run.
463
+ - Trace finding: the old timer hypothesis is no longer the main issue.
464
+ - `TimerFire` on `CrRendererMain` is now small overall and no longer explains the visible hitch pattern.
465
+ - `raw-image-decoder.worker` is effectively idle, so the previous fallback decode path is no longer the dominant cost either.
466
+ - The remaining hot path is live `MessagePort` delivery into:
467
+ - `src/messaging/message-handler.ts`
468
+ - `src/connection/foxglove-connection.ts`
469
+ - `src/context/MessagePipelineProvider.tsx`
470
+ - `src/context/message-pipeline-store.ts`
471
+ - `src/messaging/utils.ts`
472
+ - `src/panels/image/ImageCanvasRenderer.tsx`
473
+ - The periodic spikes visible in the trace line up more with GC/allocation cleanup than with a repeating app-owned timer callback.
474
+ - Added a live message-subscription controller to `src/context/MessagePipelineProvider.tsx`.
475
+ - Updated `src/messaging/utils.ts` so `useMessageSubscription()` now uses that live controller instead of subscribing through the Zustand `messageEventsBySubscriberId` path.
476
+ - Result: `ImageCanvasRenderer` now receives current-frame image/annotation batches directly from the listener path without registering as a store subscriber and without forcing per-frame `messageEventsBySubscriberId` churn for the image panel.
477
+ - Preserved mount-time preload behavior by replaying cached last-topic events from the pipeline store when a live subscriber attaches.
478
+ - Removed temporary encoded-image diagnostics from the hot path:
479
+ - `src/messaging/message-handler.ts`
480
+ - `src/messaging/deserialization.worker.ts`
481
+ - `src/panels/image/ImageCanvasRenderer.tsx`
482
+ - deleted `src/messaging/encoded-image-diagnostics.ts`
483
+ - Added direct connection-owned live frame dispatch in `src/connection/foxglove-connection.ts` and gated `messageEvents` publication in `src/context/MessagePipelineProvider.tsx` so one-panel live image streaming can bypass per-frame `PlayerState`/store churn when no store-based message subscribers are present.
484
+ - Updated `src/panels/image/ImageCanvasRenderer.tsx` to remove a few remaining per-frame React/annotation allocations from the hot draw path.
485
+ - Analyzed `trace13.json` after the pipeline/store bypass work.
486
+ - Trace finding: renderer-main costs dropped materially and the old timer theory is effectively dead.
487
+ - `HandlePostMessage` and image-panel callback costs both fell again versus `trace12.json`.
488
+ - No meaningful timer, major GC, or layout/paint spikes remained on `CrRendererMain`.
489
+ - The visible symptom therefore no longer lined up with a renderer-main periodic timer stall inside `lib/`.
490
+ - Broadened the investigation from renderer-main timers to end-to-end live frame cadence.
491
+ - Updated `src/messaging/deserialization.worker.ts` so `handleMessageToDecode()` resolves when decode work actually completes.
492
+ - Updated `src/messaging/message-handler.ts` with a per-topic latest-frame dispatch policy for image messages:
493
+ - only one image decode per topic may be in flight
494
+ - a newer pending image packet replaces an older unsent one while the worker is busy
495
+ - non-image messages keep the existing direct dispatch behavior
496
+ - Analyzed `trace15.json` after the worker-dispatch coalescing change.
497
+ - Trace finding: renderer-main stayed in the improved low-cost state, but dedicated worker activity still looked like bursty encoded-frame catch-up rather than a new main-thread hotspot.
498
+ - `HandlePostMessage` / `FunctionCall` on `CrRendererMain` stayed below the earlier `trace12.json` totals.
499
+ - The remaining heavy work clustered on dedicated/background decode threads.
500
+ - Reduced `VideoDecoder` backlog depth for live encoded streams in:
501
+ - `src/messaging/deserialization/video/h264.ts`
502
+ - `src/messaging/deserialization/video/h265.ts`
503
+ - H.264/H.265 now start dropping earlier when `decodeQueueSize` backs up, reducing the chance that WebCodecs accumulates a long burst of decoded frames before the latest-frame policy can discard stale output.
504
+ - Reviewed the image/annotation synchronization path after the continued hitch reports.
505
+ - Finding: there is no local image-panel logic in `lib/` that waits for a matching annotation timestamp before presenting an image frame.
506
+ - `src/panels/image/ImageCanvasRenderer.tsx` always renders the latest image immediately and overlays whichever annotation payloads are currently cached by topic.
507
+ - The only explicit wait helper in the local pipeline is `src/context/pause-frame.ts`, but the local message pipeline store exposes a no-op `pauseFrame()` and the image panel does not use it.
508
+ - The timestamp-matching sync utility in `src/utils/poitcloud-sync.ts` is specific to point-cloud/RGBD flows, not plain H.264 image presentation.
509
+ - Tightened annotation consumption in `src/panels/image/ImageCanvasRenderer.tsx` so the panel subscribes only to currently enabled annotation topics instead of subscribing to all annotation topics up front.
510
+ - Result: disabled extra annotation topics no longer deliver messages or schedule redraws for the image panel, which removes one more nonessential per-frame/per-annotation path during normal streaming.
511
+ - Added `src/utils/runtime-config.ts` as a Luxonis-owned shared runtime-config surface for browser-only config values read from `localStorage`.
512
+ - Moved duplicated runtime parsing/caching logic into that helper for:
513
+ - `neuralCameraIntrinsics`
514
+ - `stereoDepthMaxValue`
515
+ - `perspective`
516
+ - Updated these callers to use the shared runtime-config helper instead of reimplementing their own `localStorage` parsing and cache state:
517
+ - `src/messaging/message-handler.ts`
518
+ - `src/connection/foxglove-connection.ts`
519
+ - `src/messaging/deserialization/pointcloud/poitcloudPoolManager.ts`
520
+ - `src/panels/PointCloudPanel.tsx`
521
+ - Result: Phase 1 now has a single internal place for the active browser runtime decode/render settings that were previously scattered across multiple subsystems.
522
+ - Replaced the old class-based `ConfigStore` singleton in `src/utils/config-store.ts` with a plain package-local module API:
523
+ - config types/defaults
524
+ - `normalizeConnectionConfig()`
525
+ - `createConnectionConfigState()`
526
+ - Updated these callers to use the plain config API instead of the mutable singleton class:
527
+ - `src/connection/connection.ts`
528
+ - `src/messaging/message-handler.ts`
529
+ - `src/messaging/deserialization.worker.ts`
530
+ - `src/messaging/decode-core.ts`
531
+ - `src/messaging/decoder-harness.ts`
532
+ - Result: the remaining connection-config path is now explicit data/functions rather than a hidden class singleton shared across the package.
533
+ - Added `VisualizerRawImage` to `src/messaging/message-event.ts` as a local visualizer-owned raw-image shape for internal decode/render flows.
534
+ - Kept `ExtendedRawImage` as a local extension of that new type, so existing image presentation behavior and extra fields stay unchanged.
535
+ - Updated internal raw-image producers/consumers to use the local type instead of importing Foxglove `RawImage`:
536
+ - `src/messaging/deserialization/video/mono.ts`
537
+ - `src/messaging/deserialization/video/depth.ts`
538
+ - `src/messaging/deserialization/video/rgbd-to-pointcloud.ts`
539
+ - `src/messaging/deserialization/video/h264.ts`
540
+ - `src/messaging/deserialization/video/h265.ts`
541
+ - Result: the internal raw-image path no longer depends on Foxglove schema types just to describe local message objects.
542
+ - Added `VisualizerPointCloud` and related local point/pose helper types to `src/messaging/message-event.ts`.
543
+ - Updated internal point-cloud producers/aliases to use the local visualizer-owned point-cloud shape instead of importing Foxglove `PointCloud` as an internal type:
544
+ - `src/messaging/deserialization/pointcloud/point-cloud.ts`
545
+ - `src/messaging/deserialization/video/depth.ts`
546
+ - `src/messaging/deserialization/video/depth-to-pointcloud.ts`
547
+ - Result: the internal point-cloud decode path no longer depends on Foxglove schema types just to describe local point-cloud message objects.
548
+ - Added local visualizer-owned annotation shape types to `src/messaging/message-event.ts`:
549
+ - `VisualizerImageAnnotations`
550
+ - `VisualizerPointsAnnotation`
551
+ - `VisualizerTextAnnotation`
552
+ - `VisualizerCircleAnnotation`
553
+ - `VisualizerColor`
554
+ - Updated internal annotation producers/consumers to use those local shapes instead of Foxglove `ImageAnnotations` object types:
555
+ - `src/messaging/deserialization/detections/detection.ts`
556
+ - `src/messaging/deserialization/detections/custom.ts`
557
+ - `src/panels/image/ImageCanvasRenderer.tsx`
558
+ - `src/panels/image/annotation-overlay.ts`
559
+ - Kept `PointsAnnotationType` enum imports for now so emitted/rendered semantics remain unchanged while removing the heavier object-shape coupling.
560
+ - Result: the internal annotation path no longer depends on Foxglove schema object types just to describe local annotation messages.
561
+ - Added `src/messaging/schema-constants.ts` for local schema-compatible constants used by emitted message objects.
562
+ - Moved point-cloud field datatype constants off the Foxglove schema enum and onto local `VisualizerNumericType` constants in:
563
+ - `src/messaging/deserialization/pointcloud/point-cloud.ts`
564
+ - `src/messaging/deserialization/video/depth-to-pointcloud.ts`
565
+ - `src/messaging/deserialization/video/rgbd-to-pointcloud.ts`
566
+ - Result: internal point-cloud message construction no longer imports Foxglove `NumericType` just to assign field datatype numbers.
567
+ - Extended `src/messaging/schema-constants.ts` with a local `VisualizerPointsAnnotationType` compatibility enum using the installed Foxglove schema values:
568
+ - `UNKNOWN = 0`
569
+ - `POINTS = 1`
570
+ - `LINE_LOOP = 2`
571
+ - `LINE_STRIP = 3`
572
+ - `LINE_LIST = 4`
573
+ - Replaced the remaining internal `PointsAnnotationType` imports in:
574
+ - `src/messaging/deserialization/detections/detection.ts`
575
+ - `src/messaging/deserialization/detections/custom.ts`
576
+ - `src/panels/image/annotation-overlay.ts`
577
+ - `src/messaging/decoder-fixtures.ts`
578
+ - Result: internal annotation production, rendering, and fixture assertions no longer depend on the Foxglove schema enum directly.
579
+
580
+ ## Hitch Investigation Summary
581
+
582
+ - The original renderer-main timer hypothesis has been substantially mitigated and is not the best restart point for future debugging.
583
+ - Confirmed app-owned repeating timers reachable during normal streaming were:
584
+ - `src/messaging/rate-limiter.ts`
585
+ - `src/messaging/event-loop-delay-sampler.ts`
586
+ - `src/components/shared-interval.ts`
587
+ - `src/connection/webrtc/comms-proxy.ts`
588
+ - Removed the eager connection-owned timer path by deleting:
589
+ - `src/messaging/rate-limiter.ts`
590
+ - `src/messaging/event-loop-delay-sampler.ts`
591
+ and by removing the corresponding eager usage from `src/connection/foxglove-connection.ts`.
592
+ - The hitch persisted after removing those timers, so they were not the sole cause.
593
+ - Subsequent traces shifted the remaining hot path into live message delivery and image presentation:
594
+ - `src/messaging/message-handler.ts`
595
+ - `src/connection/foxglove-connection.ts`
596
+ - `src/context/MessagePipelineProvider.tsx`
597
+ - `src/context/message-pipeline-store.ts`
598
+ - `src/messaging/utils.ts`
599
+ - `src/panels/image/ImageCanvasRenderer.tsx`
600
+ - Mitigations implemented during the investigation:
601
+ - bypassed Zustand `messageEventsBySubscriberId` churn for live image-panel subscriptions
602
+ - added direct connection-owned live frame dispatch
603
+ - stopped publishing per-frame `PlayerState` updates when no store-based subscribers need them
604
+ - removed temporary encoded-image diagnostics from the hot path
605
+ - trimmed per-frame allocations in `ImageCanvasRenderer`
606
+ - added per-topic latest-frame dispatch in `src/messaging/message-handler.ts`
607
+ - reduced H.264/H.265 `VideoDecoder.decodeQueueSize` backlog threshold from `12` to `3`
608
+ - limited image panels to enabled annotation-topic subscriptions only
609
+ - `trace8.json` changed the next focus again:
610
+ - the old roughly-5-second hitch pattern no longer showed up as a dominant periodic renderer-main spike
611
+ - the remaining top app-owned cost on `CrRendererMain` was steady `HandlePostMessage` / callback churn, not `FireAnimationFrame`, React commit, or decode worker compute
612
+ - the hottest non-extension main-thread bundle region mapped back to the local message pipeline / decoded-message delivery path rather than the WebGL image renderer
613
+ - Implemented after `trace8.json`:
614
+ - replaced one-decoded-event-per-post delivery with worker-side batched decoded-message delivery in:
615
+ - `src/messaging/deserialization.worker.ts`
616
+ - `src/messaging/message-handler.ts`
617
+ - `src/messaging/message-event.ts`
618
+ - decoded events are now coalesced to latest-per-topic for image-like schemas before crossing the `MessagePort`, and superseded `renderableBitmap` objects are closed on the worker side
619
+ - transport batching and decoded-event flushing had already been moved off `setTimeout(0)` / `requestAnimationFrame` onto microtasks, so the new batch delivery stacks on top of that lower-latency path
620
+ - Browser follow-up after the decoded-message batching change:
621
+ - the user reported the visible hitching appeared to be gone
622
+ - the remaining symptom shifted to bursty H.264 cadence rather than obvious UI stalls
623
+ - Implemented after that report:
624
+ - restored real compressed-input shedding for normal native H.264/H.265 image playback in:
625
+ - `src/messaging/deserialization/video/h264.ts`
626
+ - `src/messaging/deserialization/video/h265.ts`
627
+ - once `VideoDecoder.decodeQueueSize` is already at the shallow backlog limit, native image playback now drops backed-up `delta` frames instead of decoding them late and presenting catch-up bursts
628
+ - conservative `outputMode: "i420"` paths used for RGBD / point-cloud extraction still do not shed compressed frames
629
+ - Later traces (`trace13`, `trace15`, `trace16`) showed materially lower renderer-main costs and no dominant app-owned periodic timer spike.
630
+ - Annotation synchronization was checked explicitly and ruled out for plain image display:
631
+ - `src/panels/image/ImageCanvasRenderer.tsx` does not wait for timestamp-matched annotations before presenting the latest image
632
+ - `src/context/pause-frame.ts` is not used by the local image path
633
+ - `src/utils/poitcloud-sync.ts` applies to point-cloud/RGBD synchronization, not plain H.264 image panels
634
+ - Current conclusion:
635
+ - the renderer-main timer theory is largely dead
636
+ - the previous visible hitch was likely dominated by decoded-message delivery/task churn on the main thread
637
+ - after batching that path away, the remaining encoded-video risk moved to decode pacing / catch-up cadence
638
+ - future hitch work should resume from that point instead of re-running the earlier timer investigation
639
+
640
+ ## Validation Run
641
+
642
+ - 2026-05-07 hitch-follow-up validation:
643
+ - `npm exec -- tsc -p tsconfig.json --noEmit`
644
+ - `npm run build:visualizer-protobuf`
645
+ - repeated after:
646
+ - decoded-message worker batching
647
+ - native H.264/H.265 delta-frame shedding
648
+ - Build results:
649
+ - targeted visualizer package typecheck passed
650
+ - `build:visualizer-protobuf` passed after both follow-up changes
651
+ - remaining output was limited to existing non-failing warnings:
652
+ - Rollup `"this" has been rewritten to "undefined"`
653
+ - existing circular dependency warning around `Panel.tsx`
654
+ - OMT worker-format warning
655
+ - Trace status for this session:
656
+ - `trace8.json` was captured and inspected locally with ad hoc Node scripts against:
657
+ - `CrRendererMain`
658
+ - dedicated worker threads
659
+ - top `FunctionCall` / `HandlePostMessage` callsites in the built Visualizer bundle
660
+ - no new post-fix browser trace was captured from this terminal-only environment after the batching and delta-shedding changes
661
+ - Browser traces captured during this investigation include:
662
+ - `trace7.json`
663
+ - `trace8.json`
664
+ - `trace9.json`
665
+ - `trace10.json`
666
+ - `trace11.json`
667
+ - `trace12.json`
668
+ - `trace13.json`
669
+ - `trace15.json`
670
+ - `trace16.json`
671
+
672
+ ## Known Open Risks
673
+
674
+ - The new WebGL fast path only covers the common packed and YUV live formats. Unsupported formats still use the old worker decode path and may still hitch independently.
675
+ - The packed-format WebGL path currently requires row stride to be pixel-aligned (`step % bytesPerPixel === 0`). Padded packed formats that are not pixel-aligned still fall back to CPU conversion.
676
+ - This session did not record a fresh browser trace after the decoded-message batching change or the follow-on delta-frame shedding change, so the final browser confirmation still needs manual repro with `?streamDiagnostics=1` on:
677
+ - Visualizer H.264
678
+ - Viewer H.264
679
+ - raw-image baseline
680
+ - H.265 if available
681
+ - If decode throughput is truly lower than ingress for a given device/browser, the new native-path delta shedding may trade the old hitch for visible temporal sparsity or motion burstiness. That is an intentional low-latency tradeoff, but live browser validation is still required.
682
+ - `outputMode: "i420"` paths still do not shed compressed frames, so RGBD / point-cloud extraction may retain different burst behavior from plain image playback under the same source stream.
683
+ - Diagnostics currently focus on the encoded image path and image-panel render cadence. They do not yet enumerate every repeating timer in the app shells automatically.
684
+ - This fixes the concrete `Panel`-level update loop for annotation-disabled panels. If the point-cloud panel still fails after this, the remaining issue is likely a separate render exception in the point-cloud renderer rather than another generic React depth loop from the wrapper.
685
+ - This fixes the boundary reset loop itself, but the original render exception that first trips the panel boundary may still exist elsewhere; if the fallback still appears, the next step is to capture the non-minified error from the underlying panel renderer.
686
+ - Generated protobuf files and Tailwind output are now intentionally untracked, so clean builds in fresh clones depend on running `npm run gen:proto` and `npm run tailwind` before steps that expect those generated artifacts to exist on disk.
687
+ - Full `npm run gen:proto` was not executed in this session because the protobuf download step requires network access; the plugin-path fix is validated locally but not end-to-end against GitHub fetches here.
688
+ - The generator still depends on external `protoc`, `curl`, and `jq` binaries being installed in the caller environment.
689
+ - Browser-runtime validation is still needed if hitch work resumes; the encoded-video hitch remains unresolved.
690
+ - Browser-runtime validation is still needed if hitch work resumes; the original hitch may be substantially improved, but the remaining H.264 pacing behavior is not yet characterized with a new clean trace.
691
+ - `src/components/shared-interval.ts` remains an active renderer-main interval when UI metrics consumers are mounted, though it should be excluded by the reported "no toolbar metrics" reproduction.
692
+ - The store still caches `lastMessageEventByTopic` for all live messages, so some per-frame allocation remains even after bypassing `messageEventsBySubscriberId` for the image panel.
693
+ - The remaining symptom may now be dominated by browser/runtime video decode cadence, decode-queue policy, or `VideoDecoder` recovery behavior rather than a clearly removable `lib/` timer or store hot path.
694
+ - This annotation-subscription reduction only helps if the repro stream advertises annotation topics; it does not explain hitching on a pure image-only stream with no annotation traffic.
695
+ - The hitch investigation produced several useful mitigations and dead-end eliminations, but not a full fix.
696
+ - Browser trace artifacts collected during the hitch investigation were removed from the repo root after the findings were summarized here.
697
+ - Rewrote `feat/visualizer-v4` history to purge committed browser trace artifacts from reachable history so the branch can be pushed again.
698
+ - Created backup branch `backup/feat-visualizer-v4-before-trace-purge` before the history rewrite.
699
+ - Connection/runtime configuration is cleaner now, and decode/point-cloud settings have an explicit exported package API through `setRuntimeConfig()` / `getRuntimeConfig()` / `resetRuntimeConfig()`.
700
+ - Legacy `localStorage` keys for `neuralCameraIntrinsics`, `stereoDepthMaxValue`, and `perspective` are now only a bootstrap compatibility fallback when the runtime-config module first loads.
701
+ - Foxglove schema object/type coupling on the image and point-cloud decode/render path is now much smaller, but other Foxglove schema/runtime dependencies still remain elsewhere in the package.
702
+ - The bundle no longer needs live localization runtime packages, but the legacy Foxglove-derived point-cloud/context code still imports some translation tables and key helpers, so bundle-size cleanup is not complete yet.
703
+ - The narrow localization-specific cleanup is close to exhausted. The remaining bundle weight is now mostly structural Foxglove-derived UI/runtime code, not translation runtime or translation-table payloads.
704
+ - `npm run build` succeeds, but existing Rollup warnings still indicate unresolved dependency and asset-alias debt in the broader Foxglove-derived build path.
705
+ - The legacy rate limiter is now an explicit cleanup candidate, not just a diagnostic finding. If no active runtime contract turns up during implementation, it should be removed rather than carried forward.
706
+ - The easy build-warning cleanup is largely exhausted too. The remaining unresolved-dependency warnings did not disappear after making package metadata explicit, which points to Rollup/workspace resolution behavior or deliberate externalization decisions rather than simple undeclared-package debt.
707
+ - `src/` no longer imports `@foxglove/studio-base`, `@foxglove/studio`, or `@foxglove/ws-protocol`.
708
+ - The package now builds from repo root and no longer depends on the removed `packages/` workspace tree or old Rollup resolver hints.
709
+ - Package metadata is cleaner, but third-party published ESM surfaces still influence which modules must stay explicit Rollup externals even when `src/` no longer imports them directly.
710
+ - Browser-runtime validation is still needed if hitch work resumes; the encoded-video hitch remains unresolved.
711
+ - Browser-runtime validation is still needed if hitch work resumes; the remaining issue may now be "bursty but current" playback instead of hard hitching.
712
+ - `debugLogs` support now uses the explicit runtime-config API too. The old `connectionConfig` storage shape is only read once as a compatibility bootstrap.
713
+ - Runtime-config change propagation is now live for existing deserialization workers too; toggling `debugLogs` through `setRuntimeConfig()` updates already-created worker instances instead of only affecting future ones.
714
+ - After the conservative dependency refresh, the remaining outdated packages are mostly major-version or broader ecosystem moves rather than easy same-major bumps:
715
+ - MUI 5 -> 9
716
+ - Three 0.156 -> 0.184
717
+ - Zustand 4 -> 5
718
+ - legacy lint stack major updates
719
+ - TypeScript 5 -> 6
720
+ - Panda CSS replaced by Tailwind CSS and shared UI packages
721
+ - Webpack dev tooling major updates
722
+ - `@luxonis/ui-components` and `@luxonis/ui-utils` are now the shared UI layer for the workspace, and the root package no longer directly depends on MUI or Emotion for its own source/runtime path.
723
+
724
+ ## Exact Next Task
725
+
726
+ - Re-run the encoded-stream repro matrix on the latest build in a browser with `?streamDiagnostics=1`:
727
+ - Visualizer H.264
728
+ - Viewer H.264
729
+ - H.265 if available
730
+ - compare against raw-image baseline
731
+ - Capture a fresh Chrome Performance trace after the decoded-message batching change and the native delta-frame shedding change.
732
+ - Confirm whether:
733
+ - the previous visible hitch pattern is still gone
734
+ - main-thread `HandlePostMessage` volume is materially lower than `trace8`
735
+ - the new remaining symptom is bursty decode pacing rather than renderer-main overload
736
+ - If playback is still bursty, inspect stream diagnostics and the trace for:
737
+ - sustained `VideoDecoder.decodeQueueSize` growth
738
+ - repeated delta-frame dropping without timely keyframe recovery
739
+ - differences between native image playback and RGBD `i420` extraction behavior
740
+ - If another code round is needed after that trace, the next likely lever is tuning native H.264/H.265 backlog shedding policy:
741
+ - lower the backlog threshold from `3` to `2` for plain image topics only
742
+ - or make shedding adaptive by observed queue growth instead of one fixed threshold
743
+
744
+ ## Baseline Findings
745
+
746
+ - `lib/` is not fully self-contained yet, but it no longer builds or type-checks against `../packages/studio-base/src`, `../packages/theme`, or Rollup `../packages` resolution hints.
747
+ - Both `ImagePanel` and `PointCloudPanel` still depend on Foxglove rendering internals.
748
+ - `VisualizerContext` still recreates a trimmed Foxglove Studio runtime with several stubbed providers.
749
+ - Decode architecture currently uses:
750
+ - transport worker
751
+ - adapter
752
+ - one deserialization worker per topic
753
+ - nested depth and point-cloud worker pools
754
+ - Supported input schemas currently include:
755
+ - `EncodedFrame`
756
+ - `ImgFrame`
757
+ - `ImgDetections`
758
+ - `ImageAnnotations`
759
+ - `SpatialImgDetections`
760
+ - `IMUData`
761
+ - `PointCloudData`
762
+ - `RGBDData`
763
+
764
+ ## Known Hotspots
765
+
766
+ - Per-topic decoder workers plus nested worker pools create high thread count and likely extra buffer copies.
767
+ - H.264/H.265 decode paths repack buffers per frame.
768
+ - `estimateObjectSize()` is called on hot paths.
769
+ - Annotation toggles remount whole Foxglove panels.
770
+ - Message pipeline is effectively single-flight under render pressure.
771
+ - Point-cloud worker pool is mostly serialized despite multiple workers.
772
+ - Point-cloud sync queue uses O(n) cleanup.
773
+ - Rate-limiting behavior appears partially broken.
774
+
775
+ ## Baseline Validation
776
+
777
+ Command run:
778
+
779
+ ```bash
780
+ yarn tsc -p tsconfig.json --noEmit
781
+ ```
782
+
783
+ Current result:
784
+
785
+ - Passes.
786
+
787
+ Other notes:
788
+
789
+ - No library-owned tests or fixture harness were found in `lib/`.
790
+ - The previous branch-local `runtime-config-storage.ts` WIP was removed and no longer affects the baseline.
791
+
792
+ ## Validation For Latest Checkpoint
793
+
794
+ Commands run:
795
+
796
+ ```bash
797
+ yarn tsc -p tsconfig.json --noEmit
798
+ yarn fixtures:decode
799
+ ```
800
+
801
+ Current result:
802
+
803
+ - `yarn fixtures:decode` succeeds and all current built-in fixtures pass:
804
+ - raw color image frame
805
+ - IMU data
806
+ - colored point cloud
807
+ - uncolored point cloud
808
+ - image detections
809
+ - spatial image detections
810
+ - custom image annotations
811
+ - `yarn tsc -p tsconfig.json --noEmit` passes.
812
+ - The fixture runner still emits Node loader warnings because it currently uses `ts-node/esm` with `--experimental-specifier-resolution=node`.
813
+ - The fixture runner is intentionally limited to browser-independent decode behavior. Browser-native paths still need browser-runtime validation.
814
+ - Browser-runtime validation now has a checked-in entrypoint, but it was not executed in this session because the current environment does not provide a browser.
815
+ - The local panel-shell cleanup preserved the same fixture results and the branch still type-checks cleanly.
816
+ - The panel-facing renderer/camera/type cleanup preserved the same fixture results and the branch still type-checks cleanly.
817
+ - The local image panel host preserved the same fixture results and the branch still type-checks cleanly.
818
+ - The local image panel host subscription-loop fix preserved clean TypeScript validation.
819
+ - The local image panel callback-loop fix preserved clean TypeScript validation.
820
+ - The local image panel visual and metric alignment cleanup preserved clean TypeScript validation and fixture results.
821
+ - The encoded-video queue stabilization change preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because current checked-in fixtures do not yet cover H.264/H.265 sample playback.
822
+ - The encoded-video output scheduling change also preserves clean TypeScript validation. Browser-runtime hitch behavior still still needs direct validation.
823
+ - The native `NV12` fast path preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation.
824
+ - The new encoded-video `ImageBitmap` fast path preserves clean TypeScript validation. Browser-runtime hitch behavior still still needs direct validation because this environment cannot run the browser stream.
825
+ - The encoded-video payload-transfer cleanup preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because this environment cannot run the browser stream.
826
+ - The decoded-message size reuse cleanup preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because this environment cannot run the browser stream.
827
+ - The local pipeline dispatch simplification preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because this environment cannot run the browser stream.
828
+ - The cached-frame resource trimming preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because this environment cannot run the browser stream.
829
+ - The cached raw-image payload trimming preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because this environment cannot run the browser stream.
830
+ - The panel metrics hook stabilization preserves clean TypeScript validation. Browser-runtime hitch behavior still needs direct validation because this environment cannot run the browser stream.
831
+ - The panel toolbar sampling consolidation preserves clean TypeScript validation and fixture results. Browser-runtime hitch behavior and FE delay readout still need direct validation because this environment cannot run the browser stream.
832
+ - The frontend delay sampling restoration preserves clean TypeScript validation and fixture results. Browser-runtime validation is still required to confirm that the FE delay readout is visible again and to continue isolating the unchanged H.264 hitch.
833
+ - The pipeline order-tracking removal preserves clean TypeScript validation and fixture results. Browser-runtime validation is still required to determine whether removing this legacy per-batch scan changes the remaining H.264 hitch pattern.
834
+ - Hiding the Frontend Delay metric preserves clean TypeScript validation. The H.264 hitch remains unresolved.
835
+ - The pipeline/frame snapshot allocation cleanup preserves clean TypeScript validation and fixture results. Browser-runtime validation is still required to see whether reducing this allocation churn changes the H.264 hitch or GC profile.
836
+ - The narrowed live-frame propagation preserves clean TypeScript validation and fixture results. Browser-runtime validation is still required to see whether reducing the breadth of live frame state propagation changes the H.264 hitch or GC profile.
837
+ - The imperative image-panel draw path preserves clean TypeScript validation and fixture results. Browser-runtime validation is now required to see whether removing per-frame React state churn from `ImageCanvasRenderer` changes the H.264 hitch pattern.
838
+ - The dead render-delay cleanup preserves clean TypeScript validation and fixture results. Browser-runtime validation is still required to see whether removing this confirmed periodic React state churn reduces the scheduler-driven hitch pattern.
839
+ - The native encoded-video no-raw-bytes experiment preserves clean TypeScript validation and current Node-safe fixture results. Browser-runtime validation is still required to determine whether removing worker-side `VideoFrame.copyTo()` from normal H.264/H.265 image topics materially changes the 5-second hitch profile.
840
+ - The explicit decoded-message `MessagePort` transport preserves clean TypeScript validation and current Node-safe fixture results. Browser-runtime validation is now required to confirm that encoded image topics actually arrive at `ImageCanvasRenderer` with `renderableBitmap` intact and that the `raw-image-decoder.worker` per-frame activity disappears from the next trace.
841
+ - The encoded-image bitmap-hop diagnostics preserve clean TypeScript validation and current Node-safe fixture results. Browser-runtime validation is now required to collect the new `[bitmap-path]` logs and identify the exact hop where `renderableBitmap` is lost.
842
+ - The encoded-image subscription stabilization does not introduce new TypeScript diagnostics in the touched files. A focused `npm exec -- tsc -p libraries/depthai-visualizer-lib/tsconfig.json --noEmit` run still fails on pre-existing `ArrayBufferLike` / `ImageData` typing issues in `src/connection/communicator.ts` and `src/panels/image/worker-image-decoder.ts`, so browser/runtime confirmation is still needed for this checkpoint.
843
+ - `npm run -w=@luxonis/visualizer-protobuf build` now succeeds on macOS after the protobuf `sed` fix, and the emitted `dist/` bundle contains both the encoded-frame FIFO queue change and the native-to-I420 fallback path.
844
+ - `npm run -w=@luxonis/visualizer-protobuf build` still succeeds after the `imageFrame` FIFO extension and async decode-error surfacing changes.
845
+ - The per-frame encoded output-mode fix preserves clean TypeScript validation and current Node-safe fixture results. Browser-runtime validation is now required to confirm that normal H.264 image topics start reporting `expected=true` / actual bitmap presence instead of falling straight into the `yuv420p` raw decode path.
846
+ - Verified after the branch-history rewrite that `feat/visualizer-v4` no longer contains reachable `trace*.json` blobs, including the previous >100MB files that blocked pushing.
847
+ - The local raw-image decoder replacement preserves clean TypeScript validation and current Node-safe fixture results while removing the last `@foxglove/den/image` dependency from `lib/src`.
848
+ - The localization stub pass preserves clean TypeScript validation and current Node-safe fixture results.
849
+ - The direct translation-table removal preserves clean TypeScript validation and current Node-safe fixture results.
850
+ - The protobuf generator idempotence fix restores clean validation across:
851
+ - `yarn tsc -p tsconfig.json --noEmit`
852
+ - `yarn fixtures:decode`
853
+ - `yarn build`
854
+ - `yarn build` now completes successfully, but still emits existing Rollup warnings about unresolved third-party dependencies, unresolved Foxglove font asset URLs, circular dependencies, and MUI export mismatches.
855
+ - The remaining rate-limiter removal preserves clean validation across:
856
+ - `yarn tsc -p tsconfig.json --noEmit`
857
+ - `yarn fixtures:decode`
858
+ - `yarn build`
859
+ - Build output remains successful with the same pre-existing Rollup warnings; the rate-limiter removal did not introduce any new warning class or validation failure.
860
+ - The follow-on build-warning cleanup also preserves clean validation across:
861
+ - `yarn build`
862
+ - Build improvements confirmed in this slice:
863
+ - the unresolved Foxglove font asset warnings are gone
864
+ - the previous theme-package `Missing exports` / `Unused external imports` warnings are gone
865
+ - The local Visualizer shell slimming preserves clean validation across:
866
+ - `yarn tsc -p tsconfig.json --noEmit`
867
+ - `yarn fixtures:decode`
868
+ - `yarn build`
869
+ - The local visualizer shell context replacement preserves clean validation across:
870
+ - `yarn tsc -p tsconfig.json --noEmit`
871
+ - `yarn build`
872
+ - The follow-on build cleanup removed dead `@foxglove/studio-base` aliases, the unused `camera-controls` dependency, and the last `../packages/theme` / `../packages` resolver hints while preserving clean validation across:
873
+ - `yarn tsc -p tsconfig.json --noEmit`
874
+ - `yarn build`
875
+ - The WebSocket/WebRTC transport layer now uses a local `foxglove-ws-types.ts` contract for opcodes and message/service/channel shapes; only `FoxgloveClient` remains as a direct `@foxglove/ws-protocol` import. This preserves clean validation across:
876
+ - `yarn tsc -p tsconfig.json --noEmit`
877
+ - `yarn build`
878
+ - The WebSocket worker now depends on a local `foxglove-client-adapter.ts` interface instead of importing `FoxgloveClient` directly. The direct package boundary is reduced to that one adapter file, and validation remains clean across:
879
+ - `yarn tsc -p tsconfig.json --noEmit`
880
+ - `yarn build`
881
+ - The external-subpath Rollup cleanup preserves clean validation across:
882
+ - `yarn tsc -p tsconfig.json --noEmit`
883
+ - `yarn build`
884
+ - The `"use client"` warning-filter cleanup preserves clean validation across:
885
+ - `yarn tsc -p tsconfig.json --noEmit`
886
+ - `yarn build`
887
+ - Remaining build warnings are now primarily:
888
+ - `this` rewrite notices from third-party packages
889
+ - existing circular-dependency notices
890
+ - the OMT browser-support warning
891
+ - Restored the intended native encoded-image fast path so live `native` decode now prefers `createImageBitmap(frame)` before falling back to transferable planar payloads:
892
+ - `src/messaging/deserialization/video/h264.ts`
893
+ - `src/messaging/deserialization/video/h265.ts`
894
+ - `src/messaging/deserialization/video/mjpeg.ts`
895
+ - This makes the existing `renderableBitmap` event contract live again for H.264, H.265, and MJPEG instead of leaving that path as dead scaffolding while still preserving the current planar fallback paths for RGBD and browsers where bitmap extraction fails.
896
+ - Replaced the coarse encoded-stream browser gate with target-specific runtime capability checks in `src/messaging/decode-core.ts` and `src/utils/encoding.ts`:
897
+ - video-backed encoded streams now require actual `VideoDecoder` and `EncodedVideoChunk` support
898
+ - JPEG-backed encoded streams now require actual `ImageDecoder` support
899
+ - secure-context enforcement remains unchanged
900
+ - Validation for this checkpoint:
901
+ - `npm run build:visualizer-protobuf`
902
+ - build passed
903
+ - remaining warnings were unchanged: third-party `this` rewrite notices, existing circular dependencies, and the OMT browser-support warning
904
+ - Removed legacy storage bootstrap from `libraries/depthai-visualizer-lib/src/utils/runtime-config.ts` so the library no longer reads `localStorage` on module import to discover decode/runtime settings.
905
+ - Kept `VisualizerConnection` focused on connection concerns only by removing the temporary runtime-config constructor bridge from `libraries/depthai-visualizer-lib/src/connection/connection.ts`; the explicit visualizer runtime API remains `setRuntimeConfig()` / `getRuntimeConfig()`.
906
+ - Added `packages/common/src/providers/VisualizerRuntimeConfigProvider.tsx` as the new app-owned boundary for visualizer runtime state. That provider:
907
+ - owns the React state for visualizer runtime config
908
+ - synchronizes it into `@luxonis/visualizer-protobuf` through `setRuntimeConfig()`
909
+ - keeps `stereoDepthMaxValue` persistence in the app layer for compatibility instead of in the published library
910
+ - Updated `packages/common/src/components/DepthAIContext.tsx` so npm consumers can pass an explicit `visualizerRuntimeConfig` into the provider boundary when embedding the shared entrypoint.
911
+ - Updated `packages/depthai-viewer/frontend/src/providers/ViewerProviders.tsx` so Viewer now initializes the shared provider explicitly at app startup.
912
+ - Updated `packages/depthai-viewer/frontend/src/components/MaximumDepthDistanceSlider.tsx` so the depth-distance UI reads and writes provider-owned runtime config instead of talking to `localStorage` directly.
913
+ - Removed the temporary compatibility hydration from `packages/common/src/dai-connection/connection.ts`; runtime config is now no longer smuggled through connection construction.
914
+ - Validation for this checkpoint:
915
+ - `npm run build:visualizer-protobuf`
916
+ - build passed
917
+ - remaining warnings were unchanged: third-party `this` rewrite notices, existing circular dependencies, and the OMT browser-support warning
918
+
919
+ ## Next Recommended Task
920
+
921
+ Defer the browser hitch investigation until the final performance pass, per current branch plan.
922
+
923
+ Concrete next step:
924
+
925
+ - use this build to validate whether encoded-stream artifacting is resolved without regressing decode latency
926
+ - after that, use the same revision as the baseline for the final benchmark run and the final browser hitch repro pass
927
+ - if artifacting remains, inspect `imageFrame` `BITSTREAM` metadata assumptions versus `encodedFrame` `FrameType` handling before changing presentation code
928
+
929
+ ## Open Risks
930
+
931
+ - Refactoring without fixtures will likely break compatibility accidentally because some current behavior is implicit and some internal artifacts masquerade as Foxglove schema outputs.
932
+ - Build/package cleanup will be risky until Foxglove source aliasing is removed incrementally.
933
+ - The new harness can call shared decode logic directly, but some decoder paths still schedule delayed work with timers, so fixture design will need explicit settling/flush behavior for those cases.
934
+ - The current fixture runner depends on `ts-node/esm` loader behavior and emits experimental/deprecation warnings under Node.
935
+ - Video-codec-backed fixtures may be environment-sensitive because `VideoDecoder` and worker support depend on runtime capabilities.
936
+ - Browser-only runtime assumptions are part of the product contract, so future refactors should not remove browser APIs just to satisfy Node execution.
937
+ - The current browser fixture entrypoint depends on a successful build producing `dist/browser-decoder-fixtures-entry.js`; that build now succeeds again, but encoded browser-runtime coverage is still missing.
938
+ - The new bounded worker pool hashes topics to workers, so per-topic decoder state is no longer isolated by dedicated worker process. Future changes must preserve topic-keyed decoder state inside each shared worker.
939
+ - The visualizer library no longer bootstraps runtime decode settings from `localStorage`; app-owned persistence now lives behind `packages/common/src/providers/VisualizerRuntimeConfigProvider.tsx`, and only `stereoDepthMaxValue` is still persisted for compatibility.
940
+ - The legacy non-RGBD point-cloud path is still architecturally separate from the newer RGBD worker path, so there is still duplication left even after the queue/storage cleanup.
941
+ - Browser fixture coverage still does not exercise the new transfer-oriented point-cloud worker paths in a real browser runtime.
942
+ - Player-facing state/types in the connection layer still depend on Foxglove player interfaces, so deeper de-Foxgloving there will need a deliberate compatibility decision rather than a blind helper swap.
943
+ - Connection/context code now uses a local player-type and message-pipeline implementation internally, but `src/context/MessagePipelineProvider.tsx` still provides a Foxglove-compatible context shape through `ContextInternal` so the legacy Foxglove panels can continue working.
944
+ - `npm run fixtures:decode` still relies on `ts-node/esm` loader behavior and emits experimental/deprecation warnings, so the fast Node-safe fixture runner is not yet fully modernized even though it is now package-local.
945
+ - `ImagePanel` is now local, but `PointCloudPanel` still depends on Foxglove `ThreeDeeRender`, so the `ContextInternal` compatibility layer cannot be dropped yet.
946
+ - The next meaningful slimming step is no longer a small provider swap; replacing the Foxglove `ThreeDeeRender` panel wrapper will require a deliberate local adapter for the subset of `BuiltinPanelExtensionContext` that the renderer actually uses.
947
+ - The new local image host still depends on browser runtime validation because Node fixtures only cover decode semantics, not canvas/worker presentation behavior.
948
+ - Native encoded delivery now prefers `renderableBitmap` again, so panels that rely on cached last-frame snapshots still intentionally lose that bitmap on snapshot stripping and may need a subsequent live frame after mount.
949
+ - Encoded-stream capability gating now reflects constructor availability instead of browser branding, but actual per-codec support still depends on runtime `configure()` success and browser codec support.
950
+ - `imageFrame` `BITSTREAM` payloads still do not carry `EncodedFrame.FrameType`, so that path is still inferred as keyframe-only by the current H.264/H.265 helper logic and may need separate treatment if artifacts persist after removing compressed-input shedding.
951
+ - Encoded H.264/H.265 browser playback may still hitch if the remaining cost is in worker-side `copyTo()` / `createImageBitmap()` cadence or GOP/keyframe variability rather than cross-thread copies and panel decode.
952
+ - The hitch investigation is paused, not resolved. Latest traces reduced the renderer-main timer theory substantially, but encoded-video pacing and presentation cadence are still open browser-runtime risks.
953
+ - The new per-image-topic worker routing trades worker-count for isolation. If many image topics are active simultaneously, worker proliferation may become the next limit and should be checked against real multi-stream traces.
954
+ - Cached snapshots for native encoded image topics still intentionally strip `renderableBitmap`, so a panel that mounts after the last frame and receives no subsequent live frame still cannot paint from cache alone.
955
+ - The branch history was rewritten to purge trace artifacts, so the next push must use `git push --force-with-lease origin feat/visualizer-v4`.
956
+
957
+ ## Template For Next Update
958
+
959
+ Replace the sections above with current values and keep this structure:
960
+
961
+ - Date
962
+ - Branch
963
+ - Phase
964
+ - Latest completed checkpoint
965
+ - Latest commit for this checkpoint
966
+ - What was completed
967
+ - Validation
968
+ - Open risks
969
+ - Exact next task