Repository navigation
integrate livekit capture source-clock and source-pattern - #274
stephen-derosa wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Devin Review found 2 potential issues.
3 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
|
|
||
| option(LIVEKIT_BUILD_EXAMPLES "Build LiveKit examples" OFF) | ||
| option(LIVEKIT_BUILD_TESTS "Build LiveKit tests" OFF) | ||
| option(LIVEKIT_ENABLE_CAPTURE "Build the Rust FFI with pattern and clock capture sources" OFF) |
There was a problem hiding this comment.
🔴 Release bundles cannot create capture sources
Official release builds leave LIVEKIT_ENABLE_CAPTURE off, so CaptureSource::create cannot create either built-in source. The release workflow uses release-examples, not the capture-enabled test presets.
Learn more
The public capture factories are always compiled, but the Rust implementation is gated by this CMake option. The official release workflow builds using the release-examples preset, which does not enable it. Consumers of a clean release bundle therefore cannot use either advertised source.
Example: A release built through ./build.sh release-examples --bundle includes CaptureSource::create, but awaiting a pattern-source creation future fails because the Rust FFI was built without capture-pattern.
Recommended fix: Enable the capture features in release and example presets, including the presets used by .github/workflows/make-release.yml and .github/workflows/builds.yml, or make capture support the default while explicitly allowing opt-out.
Was this helpful? React with 👍 or 👎 to provide feedback.
| -DPROTOC_PATH=${Protobuf_PROTOC_EXECUTABLE} | ||
| -DRUST_TARGET=${RUST_TARGET_TRIPLE} | ||
| -DGCC_LIB_DIR=${GCC_LIB_DIR} | ||
| -DCARGO_FEATURES=${LIVEKIT_CARGO_FEATURES} |
There was a problem hiding this comment.
🔴 Capture-enabled builds can reuse disabled FFI
When separate build directories share a Rust target, LIVEKIT_ENABLE_CAPTURE can change without rebuilding its existing FFI artifact. The new build advertises capture support while CaptureSource::create still uses the disabled library.
Learn more
The Rust library output path is shared across configurations with the same Rust profile, but the custom command only tracks Rust source files. A second build directory can see the first one's existing artifact as up to date despite requesting different Cargo features. The generated kCaptureEnabled constant then describes CMake configuration, not the library actually loaded.
Example: Build a capture-disabled Debug configuration, then configure a different Debug build directory with LIVEKIT_ENABLE_CAPTURE=ON and build without changing Rust sources. Its FFI output already exists, so Cargo is skipped and pattern creation fails despite kCaptureEnabled == true.
Recommended fix: Give each feature configuration its own Rust target/output directory, or add a feature-specific stamp that forces Cargo to run whenever the feature selection differs from the library's actual build. Ensure header generation and the selected FFI artifact use the same feature set.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
🟡 Changes recommended
Capture build dependencies can become stale, and the public class layout introduces ABI constraints that should be addressed.
4 open findings
What changed in this PR
Adds GPU-backed pattern and clock capture sources through the Rust FFI.
Changes:
- Introduces the public
CaptureSourceAPI and FFI lifecycle handling. - Enables capture features in test presets and adds unit, integration, and stress tests.
- Documents capture configuration, publishing, and lifecycle behavior.
| File | Description |
|---|---|
src/tests/unit/test_capture_source.cpp |
Tests invalid configurations. |
src/tests/stress/test_capture_source_stress.cpp |
Measures capture throughput. |
src/tests/integration/test_capture_source.cpp |
Tests end-to-end publishing. |
src/ffi_client.h |
Declares capture creation support. |
src/ffi_client.cpp |
Handles capture FFI requests and events. |
src/capture_source.cpp |
Implements capture sources. |
scripts/generate-docs.sh |
Includes capture documentation. |
include/livekit/video_source.h |
Supports adopting capture handles. |
include/livekit/livekit.h |
Exposes the capture API. |
include/livekit/capture_source.h |
Defines the public capture API. |
docs/README.md |
Links capture documentation. |
docs/capture-sources.md |
Documents capture usage. |
docs/building.md |
Documents the build option. |
CMakePresets.json |
Enables capture for test presets. |
CMakeLists.txt |
Configures and builds capture support. |
build.h.in |
Exposes capture availability. |
AGENTS.md |
Documents capture architecture and threading. |
.gitattributes |
Configures preset-file whitespace handling. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| set(LIVEKIT_CARGO_FEATURES "") | ||
| set(LIVEKIT_CAPTURE_ENABLED 0) | ||
| if(LIVEKIT_ENABLE_CAPTURE) | ||
| set(LIVEKIT_CARGO_FEATURES "capture-pattern,capture-clock") |
| FfiHandle handle_; | ||
| CaptureSourceKind kind_ = CaptureSourceKind::Pixel; | ||
| int width_ = 0; | ||
| int height_ = 0; | ||
| std::optional<VideoCodec> codec_; |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Clarify which build presets enable LIVEKIT_ENABLE_CAPTURE and the requirements for source creation. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| VideoSource(FfiHandle&& handle, int width, int height) noexcept | ||
| : handle_(std::move(handle)), width_(width), height_(height) {} |
There was a problem hiding this comment.
Should this be exposed as public API? Do we have precedent for passing in a FfiHandle in elsewhere?
| do { \ | ||
| if constexpr (!kCaptureEnabled) { \ | ||
| GTEST_SKIP() << "livekit-ffi built without the 'capture' feature; configure with -DLIVEKIT_ENABLE_CAPTURE=ON"; \ | ||
| } \ | ||
| } while (false) |
There was a problem hiding this comment.
This is a bit smelly, I feel like there's gotta be a better way to check if capture is enabled. Might be worth researching C++ best practices on dynamic library availability checking
| using namespace std::chrono_literals; | ||
| if constexpr (!kCaptureEnabled) { | ||
| GTEST_SKIP() << "capture sources are disabled in this build"; | ||
| } |
There was a problem hiding this comment.
This is cleaner than https://github.com/livekit/client-sdk-cpp/pull/274/changes#r4212095152
| /// @param config Clock source configuration. | ||
| /// @return A future that resolves to the created capture source. | ||
| /// @throws CaptureSourceError When awaiting the future if creation fails. | ||
| static std::future<std::shared_ptr<CaptureSource>> create(ClockVideoSourceConfig config); |
There was a problem hiding this comment.
Help me understand why these should be async via the std::future, I get there's some async required to set things up under the hood, but compared to something like local_video_track that's synchronous: https://github.com/livekit/client-sdk-cpp/blob/main/include/livekit/local_video_track.h#L66-L67
Additionally, every example of it being called in this PR (test code, or example docs) immediately calls .get()
Not a critical comment, but am curious/want to make sure API is aligned
|
|
||
| option(LIVEKIT_BUILD_EXAMPLES "Build LiveKit examples" OFF) | ||
| option(LIVEKIT_BUILD_TESTS "Build LiveKit tests" OFF) | ||
| option(LIVEKIT_ENABLE_CAPTURE "Build the Rust FFI with pattern and clock capture sources" OFF) |
There was a problem hiding this comment.
LIVEKIT_ENABLE_CAPTURE -> LIVEKIT_BUILD_CAPTURE?
Also should we have additional CI release artifacts with capture? like <SDK>_capture.tar.gz
| namespace livekit { | ||
|
|
||
| /// @brief Whether the Rust FFI was built with capture-source support. | ||
| inline constexpr bool kCaptureEnabled = "@LIVEKIT_CAPTURE_ENABLED@"[0] == '1'; |
There was a problem hiding this comment.
I'd prefer #define LIVEKIT_CAPTURE_ENABLED over a global bool, even though more out dated


integrate the livekit capture source-clock and source-pattern.
This is from #227 with the gstreamer and device sources stripped.