Repository navigation
sensing: stream sensors to LiveKit from the hardware encoder - #1342
Draft
gareth-morgan-nv wants to merge 4 commits into
Draft
gareth-morgan-nv wants to merge 4 commits into
gareth-morgan-nv wants to merge 4 commits into
Conversation
An --add-stream with livekit=<track> publishes that sensor as an H.264 LiveKit camera track, from the real cameras or the mock alike. It is built only with -DSENSING_LIVEKIT=ON, which downloads the pinned LiveKit C++ SDK package for Ubuntu 24.04 (x64 or arm64) and checks it against its hash. With it off, the plugin builds and behaves as before and has no LiveKit dependency. SensingCamera::update() takes a GPU snapshot of the borrowed camera frame and finishes that copy before returning, since the camera may rewrite its slot at the second following poll. One worker per sensor then reduces the snapshot if asked, converts it with the existing RGBA-to-NV12 kernel, copies it to the host and submits it. Two snapshot slots bound the memory: a newer capture replaces the one waiting, so a slow network cannot stall capture or the other sensor. Publication is paced on the capture clock (--livekit-fps), and --livekit-scale-div reduces every track by an integer divisor that must divide the sensor exactly and leave even sizes. Colours are sent as BT.601 limited range, which is what the video pipeline decodes NV12 as (measured: a full-range gray decodes two levels high and a BT.709 red comes back at 233). Each frame carries the camera sequence as its frame ID, the CLOCK_MONOTONIC capture time as its user timestamp, and the sensor's capture TSC as user data. Under bandwidth pressure the encoder lowers the frame rate, not the size. A stream with only livekit= builds no file writer and no H.264 encoder. Losing the room, or a failed publish, ends capture with an error; there is no fallback. Settings that need no network (duplicate track names, a divisor that does not fit) are refused before any connection is made, and the join token, read from a file, is never printed. The SDK is reference counted through LiveKitSdkReference, so ending the plugin's session does not shut it down under another room in the same process. Tests cover the output against a fake track (pacing, bounded replacement, ownership of the borrowed frame, conversion, reduction, failure, teardown), the plugin's command line, and, when LIVEKIT_SERVER names a livekit-server binary, a real local server with a second participant decoding the tracks: names, geometry, colours, frame IDs, capture TSC, late join and rejoin, losing the server, a bad token, and shutdown. Not verified: the encoder in every run was the SDK's software OpenH264, also when NVENC or hardware encoding was requested. The arm64 package and the JETSON backend with LiveKit were not built or run. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Free CUDA allocations when the output's constructor throws, keep the stats request off the polling loop, take the SDK reference only after initialisation succeeds, close the test subscriber's streams outside its mutex, and install the LiveKit runtime beside the plugin. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Each livekit= track now carries H.264 produced by the plugin's JetsonEncoder (the V4L2 engine on a Jetson, NVENC through libavcodec in the mock) and published through the SDK's pre-encoded source. There is no software encoder and no fallback. The encoder gains a per-unit drain, keyframe requests and a bitrate setter. The output worker applies the receiving side's keyframe and bitrate requests, recovers from a refused frame with a keyframe, and matches each unit to its capture's sequence and TSC. The SDK's LICENSE and NOTICE install beside its libraries. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
Select the V4L2 FAST hardware preset explicitly, and acquire an input buffer before the RGBA-to-NV12 conversion so a frame that will be dropped costs no conversion. Add a static receiver page for LiveKit tracks, and document the Jetson capacity limits as unmeasured. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
This branch has not been 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
Streams SENSING sensors to a LiveKit room as named camera tracks. Each track carries H.264 produced by the plugin's hardware encoder and published through the LiveKit SDK's pre-encoded source, so the SDK forwards the access units and does not encode. Optional, off unless built with
-DSENSING_LIVEKIT=ON.Stacked on the mock backend PR (#1340,
gmorgan/sensing-mock-backend). Draft until that merges and the Orin items below are checked. Review this PR's own commits only.What changed
livekit=<track>builds aJetsonEncoderfor the track (the V4L2 engine on a Jetson, NVENC through libavcodec in the mock) and publishes withEncodedVideoSourceandVideoEncoderBackend::PreEncoded. There is no software encoder and no fallback: if the hardware encoder cannot start, construction fails.JetsonEncodergains a per-unitdrain()(one unit per frame with its own stamp),request_keyframe(),set_bitrate(), akeyframeflag on each unit andbackend_name(). File recording is unchanged.update()returns, then an optional integer reduction, the encode, and one SDK call per encoded unit, off the polling loop. Two snapshot slots bound memory; a newer capture replaces the waiting one.--livekit-url,--livekit-token-file(the token never appears on the command line or in output),--livekit-fps,--livekit-scale-div,--livekit-bitrate, andlivekit=<track>on--add-stream.FASThardware preset is selected explicitly (a control separate from max-performance clocks), andsubmit()acquires an input buffer before the RGBA-to-NV12 conversion, so a frame that will be dropped costs no conversion.livekit/receiver/index.htmlis a static page using the LiveKit browser SDK (CDN, integrity-checked): server URL and subscriber token, Connect/Disconnect, status, and each subscribed video track labelled with its size in its own aspect ratio. No backend or token generator. Installed underreceiver/.cmake --installcopiesliblivekit.soandliblivekit_ffi.sobeside the plugin and the SDK's ownLICENSEandNOTICEunderlicenses/livekit-sdk/.Validation
On a desktop GPU, against a local
livekit-serverwith a second participant decoding what arrives:sensing_mock_tests: 70 cases pass withLIVEKIT_SERVERset (the server cases skip without it).Known limitations / follow-ups
JETSONbuild with LiveKit.forceIDR(), runtimesetBitrate(), the keyframe flag and the drain are written against the Multimedia API but unbuilt here.LICENSEandNOTICEare installed, butliblivekit_ffi.sobundles third-party components (WebRTC among them) whose notices the SDK package does not ship. That needs a compliance review before the binaries are distributed.output=andlivekit=runs two encoders on the one engine, so their pixel rates add. TheFASTpreset and the input-buffer reordering are unbuilt off the rig.Test plan
sensing_mock_testswithLIVEKIT_SERVERset, on a desktop GPU.-DSENSING_LIVEKIT=ON(arm64 package) and confirm a subscriber decodes the tracks.🤖 Generated with Claude Code