Skip to content

Near Complete Parity with Libcamera (and support for v0.6.0)#77

Merged
chemicstry merged 48 commits into
lit-robotics:mainfrom
SoZ0:v0.6.0
Dec 6, 2025
Merged

Near Complete Parity with Libcamera (and support for v0.6.0)#77
chemicstry merged 48 commits into
lit-robotics:mainfrom
SoZ0:v0.6.0

Conversation

@SoZ0

@SoZ0 SoZ0 commented Nov 29, 2025

Copy link
Copy Markdown
Contributor

Near Complete Parity with Libcamera (and support for v0.6.0)

Highlights

  • libcamera v0.6.0 support end-to-end: regenerated control/property metadata (new WDR/LensDewarp, RPi sync, etc.), added versioned_files/0.5.2 and 0.6.0, crate bumps (libcamera/libcamera-sys 0.6.0), and verified builds/examples against the installed v0.6 libraries.
  • Formats and colour spaces are now first-class: ColorSpace shim + Rust wrapper, stream config get/set + parse/validate helpers, generated formats::* PixelFormat constants, richer PixelFormat/PixelformatInfo helpers, and multiple new examples.
  • Camera lifecycle, streams, and signals match libcamera: start/stop/restart flows, camera lookup, stream access/config helpers, hotplug/disconnect/bufferCompleted callbacks and async channel adapters, plus new orientation/transform helpers.
  • Buffers/requests now cover fences, DMABUF import, cookies, safe buffer maps, and detailed mmap info; queueing errors return the Request for retries; cookies and fences are surfaced safely.
  • Logging, vendor feature detection, and diagnostics are aligned with upstream, and a raft of new examples exercise the new APIs (capture, hotplug, color space/format tools, DMABUF/fence, config cloning, logging, lifecycle).

libcamera v0.6.0 compatibility & versioning

  • Regenerated control/property metadata from upstream tags through v0.6.0 (including 0.5.2) and checked in the new versioned files.
  • Bumped libcamera-sys/libcamera crates to 0.6.0 and bound libcamera to libcamera-sys 0.6.0.
  • Updated framebuffer FFI for the v0.6 API change (FrameBuffer::planes returns a span): the C shim now returns an owned planes wrapper with a destroy helper; FrameBufferPlanesRef drops it correctly.
  • FrameMetadataStatus already includes Startup.
  • Added a version module exposing compile-time Version { major, minor, patch } from LIBCAMERA_VERSION_* and a runtime version string (CameraManager::version() mirrors it).
  • Workspace builds verified against libcamera v0.6 and examples run cleanly.

Formats & colour spaces

  • Added a ColorSpace C shim and Rust wrapper with enums, to/from string parsing, validity checks, and adjust/with_adjusted_for_format helpers; StreamConfigurationRef gained get_color_space/set_color_space and debug output includes color space.
  • PixelFormat grew parsing/validation helpers (from_str/is_valid, to_raw/from_raw_parts, modifier conveniences) and format-aware adjustment helpers.
  • Generated formats::* PixelFormat constants directly from libcamera/formats.h so callers can use named constants instead of hard-coded fourcc/modifier pairs.
  • PixelFormatInfo shim exposes plane layout, stride/plane_size/frame_size helpers, and V4L2 mappings without requiring libcamera internal headers when building against a system libcamera (uses them opportunistically if present).
  • Examples: color_space, color_space_parse, color_space_adjust, pixel_format_roundtrip, formats_constants, configure_formats.

Camera lifecycle, streams, configuration, and transforms

  • CameraManager lifecycle controls: new_unstarted(), start(), stop(), try_stop()/restart(), and is_started(), with handle tracking to prevent stopping while cameras are alive; manager_lifecycle example exercises the flows.
  • Camera lookup and version: CameraManager::get(id) fetches by ID (get_camera example) and CameraManager::version() returns the runtime libcamera version string.
  • Hotplug/disconnect parity: CameraManager exposes on_camera_added/on_camera_removed plus subscribe_hotplug_events() -> mpsc::Receiver; callbacks warn not to block the libcamera thread; hotplug example wires the channel.
  • Streams/config inspection: Camera::streams() now exposes active streams via a C shim; Stream::configuration() lets you inspect validated stream configs after configure().
  • Configuration helpers: Camera::generate_first_supported_configuration() tries roles in order; CameraConfiguration::add_configuration(), add_configuration_like(), and add_configurations_like() append valid stream configs (no empty placeholders) and to_string_repr/validate_and_log aid debugging.
  • Orientation and transforms: CameraConfiguration now exposes orientation getter/setter backed by libcamera::Orientation; Transform bitmask ops are fixed, orientation_from_rotation helper maps degrees to EXIF/libcamera orientations, and orientation_helpers example demonstrates the helpers.
  • Sensor configuration parity: SensorConfiguration setters/getters for analog_crop, binning, skipping, bit_depth/output_size (now returns Size) plus readback through CameraConfiguration; sensor_config_readback example prints camera/stream configs and sensor settings.
  • StreamConfigurationRef clarifies stride/frame_size as post-validate fields and exposes formats()/stream() accessors; stream set helpers are wired through the C shim.

Controls & properties

  • Generated ControlId/PropertyId enums now expose description(&self) -> &'static str across all supported libcamera versions; camera_control_id_info example prints descriptions.
  • ControlList parity: contains/len/is_empty/clear/merge (MergePolicy), info_map/id_map accessors and constructors, and from_id_map/from_info_map helpers; iteration exposes ControlIdMap (ControlIdMap::iter) and ControlList can be built from id maps; control_list_ops example exercises the surface.
  • ControlValue covers string arrays and multi-string controls without truncation; vendor_rpi/vendor_draft features now error out at compile time if headers lack vendor controls.
  • New controls and properties from upstream tags (including WDR/LensDewarp and RPi sync controls) are generated in the versioned files.

Buffers, requests, fences, and DMABUF import

  • Fence support: added a libcamera_fence_* shim and Fence wrapper; Request::add_buffer_with_fence accepts Option, AsFrameBuffer::release_fence returns a Fence (fd not closed under callers), and fences can be dup’d via to_owned_fd; fence_capture example included.
  • DMABUF import/cookies: OwnedFrameBuffer builds framebuffers from user-provided DMABUF planes (fd, offset, length) with optional cookie and an is_contiguous() helper; FrameBufferAllocator buffers expose cookie get/set; imported buffers initialize metadata sentinels to avoid uninitialized reads; owned_framebuffer and import_dmabuf_capture examples show the flow.
  • Request ergonomics: queue_request returns the Request on error so callers can fix/retry; buffer map iteration uses libcamera’s buffer map (buffers_iter/find_buffer/has_pending_buffers/to_string_repr); Request/FrameBuffer cookies are surfaced; request_introspect and request_introspect_capture examples introspect live captures.
  • Buffer events/signals: ActiveCamera exposes bufferCompleted and disconnected signals alongside requestCompleted; buffer_completed example wires per-buffer callbacks; subscribe_request_completed/subscribe_buffer_completed provide channel-based delivery with BufferCompletedEvent carrying stream/cookie/sequence safely.
  • Memory-mapping/parity fixes: MemoryMappedFrameBuffer reports writability and per-fd mapped lengths and accepts DMA-BUFs with st_size == 0; framebuffer_allocator tracks per-stream lifetimes to avoid double free; mmap_info example shows mappings.
  • Framebuffer helpers: FrameBuffer::planes() uses the owned planes wrapper, FrameMetadataStatus covers Startup, FrameBuffer/request helpers expose cookies and request(), and is_contiguous() is available on OwnedFrameBuffer.

Logging & diagnostics

  • Logging target parity: LoggingTarget now mirrors libcamera (None/Syslog/File/Stream) and LoggingStream includes stdout/stderr/custom; mappings no longer misroute Stream to Syslog.
  • Convenience helpers: configure_stderr(category, level, color), configure_stdout/category-level setters without constructing a CameraManager, and configure_logging; logging_stdout/logging examples demonstrate stdout/stderr targets and category level control.
  • Transform/logging fixes: Transform layout/bitops fixed to avoid crashes, combine/bitmask ops mirror libcamera arithmetic, and custom logging stream hook matches libcamera’s API.
  • CameraConfiguration/StreamConfiguration/Request gained to_string_repr helpers for debugging; orientation/stride/frame_size notes clarified for advanced use.

Vendor feature detection

  • Build script scans libcamera/control_ids.h and generates vendor_features::flat LIBCAMERA_HAS_* const bools, setting cfg(libcamera_has_vendor_controls) when vendor controls are present; vendor_features example shows compile-time gating.

Examples & capture ergonomics

  • New/updated examples covering the above: color_space, color_space_parse, color_space_adjust, pixel_format_roundtrip, formats_constants, configure_formats, buffer_completed, fence_capture, owned_framebuffer, import_dmabuf_capture, request_introspect, request_introspect_capture, sensor_config_readback, get_camera, hotplug, logging_stdout, manager_lifecycle, control_list_ops, mmap_info, multi_stream_clone, orientation_helpers, vendor_features.
  • jpeg_capture and video_capture now wait up to 5s for request completions to reduce spurious timeouts on slower devices.

Remaining gaps / not yet mirrored from libcamera

  • Pipeline handler/IPA internals and tuning interfaces remain out of scope; we only surface the public application-facing API.
  • No bindings for libcamera’s in-tree demo apps or event-loop helpers (Qt/GStreamer/Android); downstreams must integrate their own runtimes.
  • We don’t bundle libcamera or manage distro-specific backends (subdev routing, hotplug policies); a system libcamera install is still required.
  • Some advanced ergonomics (e.g. glib/async runtime bridges, per-pipeline quirks) remain manual—feedback and contributions welcome.

@SoZ0

SoZ0 commented Nov 29, 2025

Copy link
Copy Markdown
Contributor Author
  • Kept vendor_draft opt-in to avoid hard failures on libcamera 0.4–0.5.x; feature still usable via --features vendor_draft, and vendor example is gated accordingly (libcamera/Cargo.toml, libcamera/examples/vendor_features.rs).

  • Added per-libcamera-version target directories in the local CI entrypoint to avoid cross-version cache contamination; Docker CI image now matches the GH Actions matrix with meson via pip (docker/ci/*). Lets us test against the CI without needing to commit to GitHub

@SoZ0

SoZ0 commented Nov 29, 2025

Copy link
Copy Markdown
Contributor Author

I know this is a VERY large PR but I have included many examples all covering every feature added or changed to help with understanding what has been added.

From what I can gather this should cover over 90% of the Libcamera public facing api allowing Libcamera-rs to almost be a true complete binding for Libcamera. We are still missing a few big features like proper IPA support, but most of whats left from my understanding is a lot of the private modules not included in distro builds.

I plan to look into proper async support / threadsafe handling and ergonomic changes. All though lots of the ergonomics changes I would add to the repo start to teeter away from "Rust bindings" and more into something that I feel would likely justify its own crate.

This all really depends on how much we are comfortable straying from Libcamera to improve things like buffer management, number of lines of code to get a stream running, stream life cycle, etc. As a lot of these are quite cumbersome and are all often done in the exact same way each time with slight configuration tweaks which really only leaves large margins for oversight by ordering setup sequences wrong or simply forgetting everything required just to start a stream.

Personally for my projects I have made a wrapper around this crate to simplify a lot of this making using the crate a lot easier, but I feel it is out of scope for the repo as a whole.

As always let me know if anything needs to change or if clarification is needed.

@chemicstry

Copy link
Copy Markdown
Contributor

Wow, this is big, in a good way.

I'm currently a bit out of the loop with libcamera so I'm inclined to merge this as is, the API looks okay at first glance. I'll just run some valgrind tests.

Maybe @fishrockz has some comments?

Amazing work btw

@chemicstry chemicstry 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.

I've tested all examples and everything looks great, only issue is that one C++ warning.

While testing, I found some bugs on the main branch, for which I commited a few fixes.

Comment thread libcamera-sys/c_api/transform.cpp Outdated
@chemicstry chemicstry merged commit 419e4b1 into lit-robotics:main Dec 6, 2025
7 checks passed
@chemicstry

Copy link
Copy Markdown
Contributor

Thanks!

@hydra

hydra commented Dec 8, 2025

Copy link
Copy Markdown

This is awesome, I came here to report the libcamera 0.6.0 wasn't supported after doing some upgrades on the raspberry-pi that I'm using for testing and found that support has been added by this PR!

After upgrading the libcamera binding use this I'm happy to report that the PR for media-rs which adds Libcamera support via these rust binding works again using libcamera 0.6.0.

Mediars PR: rust-media/media-rs#10
Demo app using egui: https://github.com/MakerPnP/machine/tree/master/experimentation/media-rs-and-opencv

Thanks again! ❤️

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.

3 participants