New reference to show off a realsense viewer.#20
Conversation
jetm
left a comment
There was a problem hiding this comment.
Compared against the existing python-flask/python-yolo reference pattern; one correctness concern on the load-bearing dependency, plus a minor doc-drift note.
There was a problem hiding this comment.
Pull request overview
Adds a new realsense reference project that demonstrates a native C++ Intel RealSense “web visualizer” system extension for Avocado OS, including build tooling, runtime packaging, and end-user docs.
Changes:
- Introduces a new
realsense/reference with README + getting-started documentation. - Adds a C++17 RealSense capture + libmicrohttpd-based MJPEG/JSON server with an embedded dashboard UI.
- Adds Avocado extension configuration, systemd service unit, and compile/install/clean scripts.
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| realsense/README.md | Reference overview and metadata (targets/topics/icon) for the references index. |
| realsense/getting_started.md | Step-by-step instructions for init/build/deploy/verify/customize. |
| realsense/avocado.yaml | Defines supported targets, extensions, packages, and SDK compile steps. |
| realsense/avocado.lock | Locks distro/targets for the reference (currently only raspberrypi5). |
| realsense/app/src/CMakeLists.txt | CMake build for the realsense-visualizer executable linking to packaged deps. |
| realsense/app/src/app.cpp | Implements capture loop, HTTP endpoints, MJPEG streaming, and dashboard HTML. |
| realsense/app/overlay/usr/lib/systemd/system/realsense-visualizer.service | Installs/enables the systemd service to run the visualizer on boot. |
| realsense/app-install.sh | Installs the built binary into the extension sysroot via cmake --install. |
| realsense/app-compile.sh | Cross-compiles via generated toolchain file and CMake build directory. |
| realsense/app-clean.sh | Cleans build artifacts. |
| realsense/.gitignore | Ignores Avocado state and build output for this reference. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jetm
left a comment
There was a problem hiding this comment.
Traced all of Copilot's findings against the full app.cpp - they're all valid and worth fixing: feed_reader returning 0 (L256) is non-idiomatic and version-fragile for the MJPEG path; MHD_create_response_from_buffer/_from_callback can return NULL (L280/L294) and are used without a guard (the callback path also leaks the FeedState on that NULL); and /api/distance (L561) returns 503 for missing x/y query params, which is a client error that should be 400, not "no depth data." The README targets vs avocado.yaml supported_targets mismatch is real too - the manifest adds imx8mp-var-dart, imx95-frdm, and ucm-imx8m-plus that the README omits. The one thing not already flagged is the most serious (inline at L175): the capture-thread loop body has no exception handler, so a camera unplug mid-stream aborts the whole process. Lower-priority: g_running is never cleared (no signal handler, so the shutdown atomic is inert), libjpeg's default error_exit calls exit() on a fatal, and app-install.sh writes to DESTDIR=$AVOCADO_BUILD_EXT_SYSROOT without guarding the var is set.
- capture loop: wrap start + stream body in try/catch(rs2::error) so a mid-stream camera fault (USB unplug) reconnects instead of terminating - feed_reader: never return 0 mid-stream (MHD reads that as end-of-stream); loop until a frame is ready or shutdown - guard NULL from MHD_create_response_from_buffer/_from_callback; free FeedState when MHD doesn't take ownership - /api/distance: 400 for missing x/y params, 503 only when depth is absent - clamp the distance lookup against the depth buffer dims, not intrinsics - SIGTERM/SIGINT handlers so shutdown actually clears g_running - libjpeg: custom error_exit via setjmp so a bad frame drops the JPEG instead of calling exit() - app-install.sh: fail clearly if AVOCADO_BUILD_EXT_SYSROOT is unset - README: match frontmatter targets to avocado.yaml supported_targets
|
Pushed bc693a1 addressing the review. All inline threads (Copilot's five + the capture-loop crash and latent OOB) are fixed and resolved. The three lower-priority items from the review summary are also in this commit:
Note: I've verified every |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 12 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
realsense/app/src/app.cpp:350
/api/distanceusesstd::atoi, which silently treats non-numeric inputs as 0 (e.g.x=foo=>x=0). That makes invalid client requests look like valid measurements. Parse withstrtoland return 400 on conversion failure.
int x = std::atoi(xs);
int y = std::atoi(ys);
- json_escape: escape control chars (\n, \r, \t, \b, \f, <0x20) so device info strings can't produce invalid JSON - dashboard: build deviceBar with textContent instead of innerHTML, closing the XSS surface from /api/device values - feed_reader: encode only new frames via a frame sequence counter rather than a fixed 33ms sleep, matching capture rate (no duplicate encodes) - /api/distance: parse x/y with strtol, return 400 on non-numeric input instead of silently treating it as 0 - avocado.yaml: label the empty root password NOT FOR PRODUCTION
|
Pushed e148048 for the second review pass — all four inline threads resolved (json_escape control chars, deviceBar XSS via textContent, duplicate-encode throttle, NOT FOR PRODUCTION password note). Also addressed the low-confidence suppressed item: |
- jpeg_encode: establish setjmp before jpeg_create_compress so a longjmp can never land on an uninitialized buffer; guard destroy with a created flag and mark it volatile across setjmp - /api/distance: reject out-of-int-range x/y with 400 before narrowing the strtol result (add <limits>)
- serve the static dashboard HTML as a persistent MHD buffer instead of copying the whole page on every "/" request - build g_device_json with std::string instead of a fixed 512-byte buffer so a long device string can't truncate it into invalid JSON - getting_started.md: note the empty root SSH password is dev-only, not for production images
jetm
left a comment
There was a problem hiding this comment.
This revision addresses almost everything from the last round - NULL/lifetime checks on the MHD responses, the content-reader no longer returns a bare 0, 400-vs-503 is cleanly separated, the clamp/index dims are consistent, g_running is now driven by a real SIGTERM/SIGINT handler, the README targets match avocado.yaml, and the device bar switched to textContent (nice XSS close). Two residual items inline. One more (LOW, no clean line to anchor): app-install.sh got the AVOCADO_BUILD_EXT_SYSROOT guard this round, but app-compile.sh still expands OECORE_TARGET_SYSROOT/CROSS_COMPILE unquoted with no guard (set -e, not -u), so run outside the SDK env it emits a silently-wrong host toolchain file instead of failing - add a matching -z check for parity.
- capture_loop: also catch std::exception (e.g. std::bad_alloc from the ~1MB per-frame buffers under memory pressure) so it can't escape the thread and call std::terminate; factor the stale-mark + backoff into a shared recover() used by both handlers - jpeg_encode: qualify out/out_size volatile so their values stay defined across setjmp/longjmp (C11 7.13.2.1) before the recovery-path free
jetm
left a comment
There was a problem hiding this comment.
The two inline fixes from last round are verified good - the capture thread now catches std::bad_alloc, and out/out_size are volatile with the const_cast at jpeg_mem_dest. Three items inline: the same bad_alloc hazard is unguarded on the HTTP-callback side (feed_reader runs in an MHD worker thread) - MEDIUM; app-compile.sh still lacks the env guard app-install.sh got; and the capture-thread config setup runs just outside its try. Everything else re-verified clean (MHD NULL/lifetime, 400-vs-503, thread-safety/bounds, signal-driven shutdown, README/yaml match).
- feed_reader / handle_request: wrap bodies in try/catch(...) so a std::bad_alloc (from snapshot copy, jpeg_encode, or chunk concat) can't unwind into libmicrohttpd's C worker thread; end the feed with MHD_CONTENT_READER_END_WITH_ERROR and return MHD_NO for the request - capture_loop: construct rs2::config inside the try so a throw during stream config can't escape the thread either - app-compile.sh: guard OECORE_TARGET_SYSROOT (mirrors app-install.sh) and quote the sysroot path; fail early with a clear message outside the SDK env
jetm
left a comment
There was a problem hiding this comment.
Reviewed across several rounds; all findings are addressed and verified on 6e3a86c - the HTTP-callback threads (feed_reader/handle_request) now catch exceptions, app-compile.sh guards OECORE_TARGET_SYSROOT, and the capture config setup is inside the try. LGTM.
No description provided.