From 8e61b8903ef12871d058765a04b7aecb99d321ad Mon Sep 17 00:00:00 2001 From: Stephen DeRosa Date: Wed, 23 Sep 2026 08:36:30 +0800 Subject: [PATCH] Advertise pass-through video formats without requiring a local real encoder A pre-encoded publisher supplies its own bitstream, so it does not need a local encoder for its codec. GetSupportedFormats() previously dropped pass-through formats for codecs no real encoder factory advertised, which made pre-encoded H.265 publishes fail silently on machines without a hardware HEVC encoder: H265 never appeared in the SDP offer, the sender negotiated a different codec, and PassthroughVideoEncoder then rejected every frame with "frame codec does not match sender codec" while captureFrame kept reporting frames as accepted. Advertising the pass-through formats unconditionally is safe because the pass-through backend is never selected automatically - it is excluded from automatic fallback and only used on an explicit publish request - and Create() already fails loudly rather than falling back to a real encoder for a pre-encoded sender. Co-Authored-By: Claude Fable 5 --- .changeset/advertise-passthrough-formats.md | 8 ++++++++ webrtc-sys/src/video_encoder_factory.cpp | 22 ++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 .changeset/advertise-passthrough-formats.md diff --git a/.changeset/advertise-passthrough-formats.md b/.changeset/advertise-passthrough-formats.md new file mode 100644 index 000000000..6c4cbf436 --- /dev/null +++ b/.changeset/advertise-passthrough-formats.md @@ -0,0 +1,8 @@ +--- +webrtc-sys: patch +libwebrtc: patch +livekit: patch +livekit-ffi: patch +--- + +Advertise pre-encoded pass-through video formats even when no local encoder implements the codec, so pre-encoded H.265 publishes negotiate on machines without a hardware HEVC encoder. diff --git a/webrtc-sys/src/video_encoder_factory.cpp b/webrtc-sys/src/video_encoder_factory.cpp index e18449c87..60695b36a 100644 --- a/webrtc-sys/src/video_encoder_factory.cpp +++ b/webrtc-sys/src/video_encoder_factory.cpp @@ -393,25 +393,19 @@ VideoEncoderFactory::InternalFactory::GetSupportedFormats() const { supported_formats.end()); } - // The pass-through factory would otherwise advertise codecs no real - // encoder implements (e.g. H265 on desktops); a normal session - // negotiating such a codec would end up with a sender that cannot create - // an encoder. Only advertise pass-through formats for codecs some real - // encoder already supports. - const size_t real_format_count = formats.size(); + // Advertise pass-through formats unconditionally: a pre-encoded publisher + // supplies its own bitstream, so it must be able to negotiate codecs no + // local encoder implements (e.g. H265 on machines without a hardware + // encoder). The pass-through backend is never selected automatically (it + // is excluded from automatic fallback and only used on an explicit publish + // request), and Create() fails loudly rather than falling back when a + // pre-encoded sender cannot be built. for (const auto& backend_factory : factories_) { if (backend_factory.backend != VideoEncoderBackend::PreEncoded) { continue; } 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) { - formats.push_back(format); - } + formats.push_back(format); } } return formats;