Repository navigation
sensing: Argus capture backend and encoder DMA-BUF input - #1429
gareth-morgan-nv wants to merge 22 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
6d1bf9a to
cf8dba3
Compare
71b6bbf to
2c38aba
Compare
cf8dba3 to
0288b95
Compare
2c38aba to
27dad9c
Compare
0288b95 to
5341f7a
Compare
27dad9c to
2602fd7
Compare
5341f7a to
ab263f4
Compare
2602fd7 to
74384ee
Compare
ab263f4 to
b9c18a5
Compare
74384ee to
32272f2
Compare
32272f2 to
e28d3bc
Compare
b9c18a5 to
69d7c23
Compare
…ord the NV12M plane contract as unverified Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…d modules conditional SENSING_WITH_ARGUS now finds libnvargus_socketclient (the nvargus-daemon client, as the repository's Argus example does); the single-process libnvargus is an explicit SENSING_ARGUS_SINGLE_PROCESS option. The plan keeps build-time backend options as the path and adds a shared-module boundary only if a target shows the executable cannot start with the unused SDK linked. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…e acquire loop start() stops the sessions already repeating if a later camera fails to start, and acquire_latest() takes at most one pool's worth of buffers per call and no longer leaks the frame it holds when an acquire fails. Not built or run (no Argus SDK). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
The extra message() and endif() made CMake fail to configure with 'Flow control statements are not properly nested'. Reported by the Orin build. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
The plan lives in the git-ignored agentPlans/ folder instead. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…e only the selected backend The initialised EGL display is owned by a member, so a constructor that throws after eglInitialize no longer leaks it. An explicit --camera-backend initialises only that SDK instead of probing both. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Built and run on an AGX Orin (JetPack 6.2 / L4T R36.4.3, SENSING SHW5G GMSL cameras, Argus backend) publishing three 2560x1984 tracks to a LiveKit room consumed by the egocap backend. Four changes were needed to get from source to a running binary: - livekit_video_output: FrameMeta had no stamp_us member, so the file did not compile. Carry the frame's CLOCK_MONOTONIC time through track_in_flight and use it for the transport timestamp. - CMake: find the Multimedia API tree before the Argus block, whose header search is relative to it; previously SENSING_WITH_ARGUS=ON failed on a fresh configure unless JETSON_MMAPI_DIR was passed. - CMake: argus_capture.cpp uses the NvBufSurf allocation wrapper, so compile samples/common/classes/NvBufSurface.cpp and link libnvbufsurftransform that it depends on. - CMake: the LiveKit SDK prebuilt is tied to its Ubuntu release's glibc; pick the 22.04 or 24.04 tarball by the host's /etc/os-release (LIVEKIT_SDK_UBUNTU overrides) instead of always 24.04, which does not link on JetPack 6. README: list the build prerequisites the top-level CMake needs on a stock Jetson (CMake >= 3.24, uv, patchelf) and note the JetPack 6.2 Argus-only configuration. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: nvShawnHwang <265103681+NVshawnhwang@users.noreply.github.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…vice-tolerant query - Share the encoder's input-buffer count with the Argus pool (pool = encoder + 4, refused below encoder + 3) so the headroom cannot drift apart. - Refuse DMA-BUF input with a scale divisor before any LiveKit connection. - query() skips a device that lacks the requested sensor mode instead of failing the probe for every camera; null-check the sensor-mode interface. - Number frames from a counter when Argus returns no capture metadata, so they are not all dropped as one re-read frame. - Remove DISPLAY before the backend probes load libargus or EGL. - Update comments that described only SIPL. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…rdown - Each camera has its own thread that blocks on acquireBuffer (finite wait) and keeps only the newest frame; a camera that delivers nothing no longer holds up the others or spams the daemon with zero-timeout polls. Frames are stamped on arrival, not when the polling loop collects them. - stop() joins the acquisition threads, stops every session before waiting on any, uses a finite waitForIdle per camera, and times each blocking call so a slow one is named in the log. A session that does not go idle is marked unclean and its buffers are leaked, never freed while the hardware may still write them. A whole-teardown watchdog ends the process if the SDK never returns. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
- If creating an acquisition thread fails, join the ones already started and stop the sessions, so no thread outlives its camera. - One teardown deadline covers the whole stop(), including returning held frames to their streams, and the object destruction has its own; the call in progress is recorded before it is entered, so a call that never returns is named when the process ends. - Return the frames waiting in the slots before waiting for the sessions to go idle: an in-flight request may need a free buffer to finish. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…he process - A failed start() now uses the same teardown as stop(): it joins the workers and returns the frames they hold, which breaks the Impl -> frame lease -> Impl cycle. - A session that does not go idle after stopRepeat is fatal in this dedicated producer (the service supervisor restarts it) instead of being marked and leaked while the process retries. - The EGL display is terminated inside the destruction deadline. - Record the lease-ownership rule in the sensing AGENTS.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Frame leases are released from any thread, so they now only post the buffer's slot to a per-camera mailbox; one owner thread makes every runtime acquire, release and stop call on that camera's stream, so those calls cannot overlap. When every buffer is out the owner waits on the mailbox instead of in an acquire that needs a returned buffer. Capture stops in two parts: stop() ends capture on the owner and clears the held frame but keeps returning buffers; the owner ends when the capture object is destroyed, after the last lease is dropped. A failed start() undoes the same way. The ownership logic is SDK-free (buffer_owner.hpp) and covered by tests with a fake buffer port, run under ThreadSanitizer and AddressSanitizer. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…d, fail on a doubled return - The owner returns the cleared latest frame's buffer before it enters the blocking idle wait, since it cannot return anything inside that wait. - A buffer the stream refuses (or whose release throws) stays counted as out and ends acquisition, instead of being counted free while acquiring continues. - A rejected return from a lease (a buffer returned twice) fails the owner instead of being ignored. - The fatal-exit comment no longer says a supervisor restarts the producer; the unit's restart policy is stated where the unit is defined. - Tests for the stop ordering and the refused/throwing release. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…r is back CameraCapture::stop() now stops new captures and returns; the wait for the sessions to go idle happens when the owner ends, after every posted buffer has been returned, so it never depends on a buffer a consumer still holds. close() reports whether every buffer came back and the stream went idle; anything else ends the process. The test fake keeps a refused buffer acquired instead of freeing it, and the tests cover the wait_idle ordering, held leases at close, and the idle outcome. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
The Argus adapter compared stopRepeat's return value to STATUS_OK, which is not a valid success predicate. Acknowledge that the call returned and keep the Status check for waitForIdle. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…_usage's layout Move the check that every requested camera exists out of main.cpp into match_requested_cameras in camera_backend, so it is testable without the Argus SDK, and cover it. Shorten one usage line so clang-format keeps print_usage's existing layout instead of re-indenting the whole block. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…r helper Logger::get returns std::shared_ptr<spdlog::logger>, not a shared_ptr of isaaccapture::Logger, so the helper did not compile when the Argus backend was enabled. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
840e767 to
da3dcb8
Compare
3bd5dc6 to
3054844
Compare
…sample wrapper The Argus capture compiled NVIDIA's sample NvBufSurface.cpp from the installed tree only for NvAllocate, which pulled in libnvbufsurftransform. Call the driver's NvBufSurfaceAllocate directly, as that wrapper does, so the build uses neither the sample source nor the transform library. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
|
Built 6502215 on an AGX Orin, L4T R36.4.3 (JetPack 6.2), -DSENSING_WITH_SIPL=OFF -DSENSING_WITH_ARGUS=ON -DJETSON_MMAPI_DIR=/usr/src/jetson_multimedia_api, ENABLE_CLANG_FORMAT_CHECK=OFF. Configure passes. Compile fails in the vendored third_party/jetson_multimedia_api/classes/NvVideoEncoder.cpp: NvBufSurfaceDeviceInfo, NvBufSurfaceGetDeviceInfo and NVBUF_DRIVER_TYPE_NVGPU (lines 99-102) and V4L2_CID_MPEG_VIDEOENC_H265_DISABLE_SAO (line 808) are not declared by the R36.4.3 headers. The vendored sources are from R39.2.1 and there is no CMake switch to compile the installed /usr/src samples instead. So the Argus path can’t be run on JetPack 6.2 with this layout, which is the configuration the earlier hardware report used. Is JetPack 6.2 still meant to be supported? If so, the vendored classes need to match R36, or the build needs a fallback to the installed samples. Argus runtime (three-camera capture, owner threads, bounded shutdown) is untested here for that reason. |
|
Closing as superseded: the camera path is now the camera_streamer architecture (SIPL/Argus sender, AVS1 over TCP, PC receiver and LiveKit bridge; see #1473-#1479). Not merged; the branch and commits are kept. 🤖 Generated with Claude Code |
|
This PR is superseded by the camera_streamer PRs:
🤖 Generated with Claude Code |
Description
Stacked on #1428 (base is
gmorgan/RearchBackend), which is stacked on #1461. This branch holds the Argus capture backend and the encoder's DMA-BUF input. The Argus path was built and run on an AGX Orin with three GMSL cameras by a reviewer (see Testing and their report); the later review-driven edits listed under Testing have not been built or run. It was written against the Jetson Multimedia API and the repository's existing Argus example as the reference.core/argus_capture.*, built only with-DSENSING_WITH_ARGUS=ON, off by default): one capture session per camera, an Argus buffer stream into a pool of NvBufSurface NV12 DMA-BUFs, a repeating request pinned to the sensor mode's frame rate, and a non-blocking acquire that keeps the newest frame and returns older ones to the camera. Frames carry a lease that returns the buffer to the camera, and keeps the Argus objects alive until it does. The sensor timestamp and capture id are passed through unscaled.JetsonEncoder::submit_dmabuf): the output plane switches to V4L2 DMA-BUF memory for an encoder created for it (one input mode per encoder). The capture buffer's lease is held until the plane returns that input buffer, and released at once for a dropped frame. No CPU or CUDA copy.--livekit-scale-divabove 1.--camera-backend=auto|sipl|argusprobes both backends;SENSING_WITH_SIPL=OFFbuilds an Argus-only rig that needs no SIPL headers or configuration;--argus-mode=Kpicks the sensor mode.Not done
Type of change
Testing
clang-format-14clean; the capture factory, output, sensing camera andmain.cpppass a g++ syntax check (with and withoutSENSING_HAS_SIPL).argus_capture.cppandjetson_encoder.cppcould not be syntax-checked here (they need the Argus and Multimedia API headers).Checklist
SKIP=check-copyright-year pre-commit run --all-filesgit commit -s) per the DCO🤖 Generated with Claude Code