Skip to content

jetson h265: encoder - #1451

Open
stephen-derosa wants to merge 3 commits into
mainfrom
sderosa/jetson-h265
Open

stephen-derosa wants to merge 3 commits into
mainfrom
sderosa/jetson-h265

Conversation

@stephen-derosa

@stephen-derosa stephen-derosa commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Enable pre-encoded H265 publishing on hosts without a local H265 encoder, including forwarding encoded video from USB cameras. Raw LiveKit senders fall back to VP8 when the requested codec cannot be encoded locally.

Replace the leaked codec-query factory with queries through the existing peer connection factory. Document backend and codec-preference configuration for direct libwebrtc consumers.

Testing

  • Unit: negotiation regression tests, factory tests
  • Manual:
    • Rust: Jetson H265 encoding of stereo camera sent to the rust-dev-client over cloud SFU
    • CPP: tested on a build against this branch

@stephen-derosa stephen-derosa self-assigned this Sep 23, 2026
@stephen-derosa
stephen-derosa marked this pull request as draft September 23, 2026 00:37
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Changeset ✓

This PR includes a changeset covering all affected packages:

Package Bump
libwebrtc minor
livekit patch
livekit-capture patch
livekit-ffi patch
webrtc-sys patch

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment on lines 409 to 416
for (const auto& format : backend_factory.factory->GetSupportedFormats()) {
const bool codec_available = std::any_of(
formats.begin(), formats.begin() + real_format_count,
[&](const webrtc::SdpVideoFormat& existing) {
return IsSameCodecName(existing.name, format.name);
});
if (codec_available) {
const bool codec_listed =
std::any_of(formats.begin(), formats.end(),
[&](const webrtc::SdpVideoFormat& existing) {
return IsSameCodecName(existing.name, format.name);
});
if (!codec_listed) {
formats.push_back(format);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Raw senders negotiate unusable codecs

GetSupportedFormats advertises pass-through-only H265 to raw senders without a backend selector. Untagged Create excludes PreEncoded, so negotiation succeeds but video cannot start.

Learn more

The encoder factory’s supported formats become the default sender capabilities. The new loop adds H265 even when only the pass-through factory implements it. A sender with no PreEncoded selector can therefore advertise and negotiate H265. Its untagged encoder request follows Create, which deliberately skips pass-through during automatic fallback and returns null when no real H265 encoder exists. The LiveKit fallback path can also reset codec preferences to this default set when codec_producible is false.

Example: On a desktop without H265 hardware, a raw-video sender and an H265-only peer negotiate H265 from the newly advertised capability. Encoder creation then returns null instead of encoding the raw frames, so the published track carries no video.

Recommended fix: Separate pass-through negotiation capability from the factory’s default raw-video formats. Ensure pass-through-only formats are exposed only to senders explicitly configured with VideoEncoderBackend::PreEncoded; filtering solely in one Rust publish path does not protect direct libwebrtc callers or empty-preference fallback.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread webrtc-sys/src/video_encoder_factory.cpp Outdated
stephen-derosa added a commit that referenced this pull request Oct 20, 2026
Address review on #1451:

- List pass-through-only codecs in GetImplementations(), last and
  untagged. libwebrtc only sends a negotiated codec that appears there, so
  pre-encoded H265 on a host without an H265 encoder failed with "No video
  codecs in common". A raw sender that still lands on such a codec fails
  encoder creation and libwebrtc falls back to another negotiated codec.
- Settle a video track's codec in LocalParticipant before AddTrackRequest:
  a raw sender whose codec no local encoder produces publishes VP8, so the
  server, encodings, and republish agree with what is sent. create_sender
  no longer falls back to an empty preference list, which offered
  pass-through-only codecs to raw senders.
- Replace the leaked process-wide query factory with
  PeerConnectionFactory::video_encoder_codecs, which queries the encoder
  factory the peer connection factory owns, and add a repeated
  create/query/drop test asserting the native factory is destroyed.
- Add livekit-capture to the changeset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
stephen-derosa added a commit that referenced this pull request Oct 20, 2026
Address review on #1451:

- List pass-through-only codecs in GetImplementations(), last and
  untagged. libwebrtc only sends a negotiated codec that appears there, so
  pre-encoded H265 on a host without an H265 encoder failed with "No video
  codecs in common". A raw sender that still lands on such a codec fails
  encoder creation and libwebrtc falls back to another negotiated codec.
- Settle a video track's codec in LocalParticipant before AddTrackRequest:
  a raw sender whose codec no local encoder produces publishes VP8, so the
  server, encodings, and republish agree with what is sent. create_sender
  no longer falls back to an empty preference list, which offered
  pass-through-only codecs to raw senders.
- Replace the leaked process-wide query factory with
  PeerConnectionFactory::video_encoder_codecs, which queries the encoder
  factory the peer connection factory owns, and add a repeated
  create/query/drop test asserting the native factory is destroyed.
- Add livekit-capture to the changeset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@stephen-derosa
stephen-derosa marked this pull request as ready for review October 21, 2026 20:26
@stephen-derosa
stephen-derosa marked this pull request as draft October 21, 2026 21:03
@stephen-derosa
stephen-derosa marked this pull request as ready for review October 26, 2026 15:07
@stephen-derosa stephen-derosa changed the title h265 support for jetson jetson h265: encoder Oct 26, 2026
stephen-derosa and others added 3 commits October 26, 2026 10:22
Address review on #1451:

- List pass-through-only codecs in GetImplementations(), last and
  untagged. libwebrtc only sends a negotiated codec that appears there, so
  pre-encoded H265 on a host without an H265 encoder failed with "No video
  codecs in common". A raw sender that still lands on such a codec fails
  encoder creation and libwebrtc falls back to another negotiated codec.
- Settle a video track's codec in LocalParticipant before AddTrackRequest:
  a raw sender whose codec no local encoder produces publishes VP8, so the
  server, encodings, and republish agree with what is sent. create_sender
  no longer falls back to an empty preference list, which offered
  pass-through-only codecs to raw senders.
- Replace the leaked process-wide query factory with
  PeerConnectionFactory::video_encoder_codecs, which queries the encoder
  factory the peer connection factory owns, and add a repeated
  create/query/drop test asserting the native factory is destroyed.
- Add livekit-capture to the changeset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant