Repository navigation
camera_streamer: add SIPL camera support to the sender - #1473
Open
gareth-morgan-nv wants to merge 15 commits into
Open
gareth-morgan-nv wants to merge 15 commits into
gareth-morgan-nv wants to merge 15 commits into
Conversation
…ure backend selection CaptureFrame.h defines the boundary between a camera backend and the encoder (native NV12 surface, leased buffer, per-camera sequence, session epoch, raw sensor time with an explicit clock domain). CaptureBackend selects argus, sipl or auto from the build's available backends; the config gains capture_backend. No existing capture path is changed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
describeArgusFrame maps the client-owned NV12 DMA-BUF layout, the VI start-of-frame TSC (as the sensor time, or none when Argus reported none) and the acquire time onto the vendor-free CaptureFrame, with a lease that returns the buffer to Argus. Not yet used by StreamProcessor, and not compiled: the Jetson multimedia SDK is not available off the Orin. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
The header promised a two-plane NV12 surface but the check only rejected fewer than two planes. It now requires NV12 and exactly two planes. Not compiled here: the Jetson multimedia SDK is not available off the Orin. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…n id and keep SIPL counters out of TSC ns fields Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
… sender does not own to the encoder Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Config.cpp parses capture_backend through parseCaptureBackend, so the config test target needs CaptureBackend.cpp. Found by the native build on the Orin. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
… capture seam backend-neutral CameraCapture is the interface a capture backend implements (cameras, start, stop, acquireLatest, waitForFrame). CaptureFrame gains the surface colour range, and its clock domain for a backend counter is named for what it is (a raw counter in the backend's own units) instead of for one SDK. Comments in the seam no longer name a camera SDK; only a backend does. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
… of StereoTiming.h FrameTiming, SenderClockDomain and the sender clock readers move to FrameTiming.h, which includes no camera SDK header. The AVS1 assembler, the TCP sender, the encoder and the stereo alignment policy include it instead of StereoTiming.h, which keeps the Argus frame readers and now only pulls in Argus for code that needs it. StereoAlignmentPolicy.h declared a NULL default and relied on Argus for <cstddef>; it includes it now. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…maBuffer DmaBuffer carried an Argus stream and buffer and the release rules for them, so the encoder header included Argus and every backend's buffers looked like Argus buffers. DmaBuffer now has a neutral owner hook (DmaBufferOwner, setOwner, releaseToOwner) and its create takes a width and height. The Argus stream/buffer pair and its acquire/release rules live in ArgusBufferBinding, which only the Argus capture path uses; the behaviour is unchanged. HevcEncoder.h includes EGL's extension header itself instead of getting it from Argus. Cross-compiles for aarch64; the Argus path has not been run on a camera. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
SiplCapture adds the SIPL pipeline setup (query, ICP and ISP0 buffer allocation, NvSci sync, auto-control registration, frame and notification threads) without the RGBA conversion. Each frame is the ISP0 NvBufSurface described as a CaptureFrame, with the SIPL capture counter as its sensor time in its own clock domain and a lease that returns the buffer to SIPL. WITH_SIPL builds it as a C++17 library; the sender stays C++14. Type-checks and cross-compiles against the Orin sysroot (cross_build.sh). Not run: the SIPL pipeline has never been started here, and whether the encoder accepts the surface's DMA-BUF descriptor is unverified. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…waitForFrame capture_backend: sipl takes a sipl: section (platform JSON and name, link masks, NITO directory, ISP0 buffer count) and is validated to mono HEVC streams without a remap. SiplCapture::waitForFrame blocks on a condition variable signalled by the frame and event threads instead of polling. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
runSiplSender feeds each SIPL ISP0 frame to its stream's HEVC encoder as an external DMA-BUF and sends it as its own AVS1 bundle (independent mono streams); the frame's SIPL buffer is returned when the encoder has dequeued the input. SenderSession selects the backend from capture_backend; Argus-only builds are unchanged. Cross-compiles with and without WITH_SIPL; never run on a camera. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…d buffer Linux autotunes the send buffer up to several MB, which on a slow link hides seconds of video between the encoder and the wire. A cap pushes the backlog back to the sender, where the existing queue and the encoder back-pressure drop frames instead. Default 0 keeps the operating system's behaviour. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Tracks the encoder input slots that hold a captured frame's DMA-BUF wrapper and lease, so the backend gets each buffer back only once the encoder has dequeued it. The wrapper type is a template parameter, so the slot and lease bookkeeping is unit-tested without the encoder SDK. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…apture The per-frame path that encodes a CaptureFrame's DMA-BUF in place and sends it as its own AVS1 bundle now lives in runCaptureSender, which takes any CameraCapture and names no camera SDK. runSiplSender only builds the SIPL backend and resolves streams to SIPL pipelines, then calls it. TSC handling, frame drops when the encoder has no free input, the drain before EOS and dropping every lease before capture stops are unchanged. The Argus path stays in runConfiguredCapture: it captures into encoder-owned buffers and bundles several cameras and capture domains per frame, which this single-camera path does not model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
gareth-morgan-nv
requested review from
farbod-nv,
jiwenc-nv,
jsepulveda-nvidia and
tengw-nv
November 11, 2026 04:34
Contributor
|
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
|
This was referenced Nov 11, 2026
This was referenced Nov 11, 2026
gareth-morgan-nv
had a problem deploying
to
dev
November 11, 2026 04:54 — with
GitHub Actions
Failure
This branch had an error being deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds SIPL camera support to the camera_streamer sender. Each ISP0 frame stays a native NV12 surface and is queued to the hardware HEVC encoder through its DMA-BUF: no RGBA conversion and no CPU pixel copy. The stream uses the existing AVS1/TCP link, so the unchanged receiver decodes it into its usual CUDA IPC buffers.
The branch is three layers, in this order:
CameraCapture; SIPL uses it.What changed
CaptureFrame/CameraCapture: an SDK-free contract (camera descriptors, per-camera sequence, session identity, raw sensor time with an explicit clock domain, a native NV12 DMA-BUF surface, and a move-only lease that returns the buffer to its backend).capture_backend: auto | argus | siplin the config, with a selection function that fails with a clear message for a backend that is not built in (and forautowhen more than one is).ArgusFrameAdapterdescribes an Argus DMA-BUF capture as aCaptureFrame.DmaBufferno longer carries Argus types: an owner hook (DmaBufferOwner,releaseToOwner) replaces the Argus stream/buffer fields; the Argus pairing and its acquire/release rules move toArgusBufferBinding.DmaBuffer::createExternalwraps a DMA-BUF the sender does not own.FrameTimingand the sender clock readers move fromStereoTiming.hinto an SDK-freeFrameTiming.h.SiplCaptureimplementsCameraCapture: platform query, ICP and ISP0 buffer allocation, NvSci buffer and sync setup, tuning registration, frame and pipeline-notification threads. A frame replaced before the consumer takes it goes straight back to SIPL.CaptureSender(runCaptureSender): TCP accept and send, AVS1 stream templates and bundle assembly, one HEVC encoder per stream, and for each framewaitForFrame->acquireLatest-> wrap the DMA-BUF -> bundle registration -> encoder queue, with the lease released when the encoder dequeues the input. A frame that arrives with no free encoder input is dropped rather than waited for.EncoderInputSlotsholds the in-flight bookkeeping as a header-only template so it is unit-testable without the encoder SDK.SiplSenderis now a thin wrapper that maps streams to SIPL pipelines.sipl:section (platform JSON and name, link masks, tuning directory, ISP0 buffer count); streamdeviceis a SIPL pipeline index.network.send_buffer_kb(default 0, off) caps the kernel TCP send buffer.WITH_SIPLCMake option (off by default) builds SIPL as a separate C++17 library; the rest of the sender stays C++14 and Argus-only builds are unchanged.Validation
clang-format-14andpre-commit(CI hook set, copyright-year hook skipped as in CI) clean on the changed files of each layer.argus_sender, with-DWITH_SIPL=ONandOFF.config,capture_backend,avs1_wire,bundle_assembler(stubbed clock readers) and the newencoder_input_slots(lease held while in flight, out-of-order completion, lease dropped before its wrapper, double and out-of-range completion rejected, release-all, release on destruction), including a run under address and undefined-behavior sanitizers.WITH_SIPL=ONand the camera-free unit tests (17 of 17) on a Jetson Orin (R39.2.1). That run was on a local build that also contained the two PRs stacked after this one, not on this branch alone.camera_receiverand CUDA IPC consumer: about 30 fps decoded with no decode errors at 4 Mbit/s over WiFi. Also run on that combined build: a receiver disconnect and reconnect rebuilt the pipeline and the stream decoded again.DmaBufferchange that touches the Argus buffer lifetime has been compiled and linked but not run against an Argus camera.Known limitations / follow-ups
runConfiguredCapture) does not consumeCameraCaptureand is not changed: its buffers are client-owned encoder DMA-BUFs returned withreleaseToOwner, it acquires per capture domain, one Argus bundle can span several streams and stereo pairs, and raw NV12 output has its own copy path. Only the SIPL half goes through the shared sender.send_buffer_kbdid not change that.argus_sender.Test plan
-DWITH_SIPL=ONon an Orin with the SIPL SDK and stream with a platform JSON for your rig: same startup lines, bundles decode, a clean Ctrl-C, and a receiver-disconnect rebuild.🤖 Generated with Claude Code