Files
oak-editor/crates/oak-common
Mike-Solar fdb5caabd5 color: non-sRGB preview, per-monitor display ICC, pipeline hardening
Preview now follows the project output colorspace end to end: the
display chain derives its content space from the project's OutputColorSpec
instead of a hardcoded sRGB name, self-managed ICC transforms go through
an XYZ D65 interchange stage (OCIO cie_xyz_d65_interchange) for non-sRGB
targets, and the platform layer declares the content colorspace (gpui
submodule bump). macOS defaults to OS-managed (fixes wide-gamut UI
oversaturation); Windows ACM warns once on non-sRGB targets.

Multi-monitor: the display ICC is looked up per the window's current
screen (macOS display id, Windows per-monitor DC, X11 RandR output
profile) with a throttled poll that invalidates frame caches on moves.

Pipeline precision: 10-bit+ sources fall back to YUV444P16LE + a Rust
matrix conversion when swscale lacks F32 output (no more 8-bit
truncation); BT.709/2020 SDR decodes with BT.1886 gamma 2.4 instead of
the sRGB EOTF; working-space compositing no longer clamps RGB to [0,1]
(alpha still clamped); the output node clamps to the target gamut;
frames without colorimetry metadata convert with BT.709 defaults
(warned once) instead of passing through; scopes read the
output-colorspace signal on both F32 paths.

Also: only emit rerun-if-changed for .env when it exists (a missing file
made every build fully dirty).
2026-08-29 00:24:15 +08:00
..

oakcommon Rust crate

Status: implemented. All include/common/*.h contracts are implemented in Rust and covered by unit + C ABI integration tests (see Testing).

Scope

Replaces the C++ oakcommon module (src/common/src): config store, command-line parser, XML stream reader/writer, file functions, debug/logging, ffmpeg/OCIO/OIIO utility queries, video/subtitle params, color transform, misc utilities. Pure leaf module — depends only on oakcore-rs, quick-xml, log, ocio-rs, image, and system libraries.

Public contract: include/common/*.h (18 headers) — frozen, implemented verbatim by src/ffi.rs.

Third-party crates

Crate Version License Status
quick-xml 0.41 MIT adopted — XML reader/writer (xmlutils.rs)
log 0.4 MIT / Apache-2.0 adopted — logging facade (debug.rs); the stderr sink is retained as the always-available backend
ocio-rs 0.2.1 BSD-3-Clause adopted — real OpenColorIO access for ocioutils.rs (OcioConfig/OcioProcessor, BitDepth mapping). Pulled in via ocio-sys built with OCIO_RS_ENABLE_REAL=1 against the Homebrew OCIO install (see .cargo/config.toml)
image 0.25 MIT / Apache-2.0 adopted — per-channel bit-depth tables and 32-bit float TIFF I/O for oiioutils.rs (image_color_type_for/bits_per_channel, F32Image). Default features off, tiff only
oakcore-rs path GPL-3.0 adopted — Rational::from_double (the C++ Rational::from_double port of FFmpeg's av_d2q) for get_pixel_aspect_ratio; a hand-written port kept in the leaf crate instead of pulling in ffmpeg-next
serde_json MIT / Apache-2.0 evaluated, not adopted — the ConfigStore format is INI (QSettings-style key=value with [group] sections, %g doubles), not JSON; switching would break C++/Rust file interop
pico-args / clap MIT / Apache-2.0 evaluated, not adoptedcommandlineparser.rs must keep exact C++ quirks (case-insensitive names, first-match-wins, last-value-wins, argv[0] skipping, truncating getter copies, borrowed C ABI handles) that a generic parser cannot express without changing the C ABI shape

Architectural decisions

  1. Leaf module discipline: no bridge/ to other oak modules. FFmpeg is reached through ffmpeg_bridge's C ABI (narrow extern "C" blocks in ffmpegutils.rs); OCIO and OIIO access is pure Rust via the crates.io bindings listed in the table above (ocioutils.rs, oiioutils.rs).
  2. olive::Variant disappears: it exists in C++ only because QVariant left a hole. Rust modules use closed enums; nothing in common needs it. variant.{h,cpp} (C++) is retired when all consumers are Rust.
  3. XML: XmlStreamReader/Writer keep the C++ streaming API shape (the C ABI is built on it), implemented over quick-xml — behavior (attribute order, error semantics) pinned by tests against the C++ oracle.
  4. Config: the ConfigStore is INI-backed (QSettings-style key=value with [group] sections, ;/# comments, %g double formatting), keeping the exact C++ file format and lookup order (user config → app defaults). It is not JSON — an earlier draft described it as JSON-backed, which was wrong; that claim was removed from this document.
  5. Logging: debug.rs provides the leveled logger (qWarning/qDebug/qCritical/qInfo replacement) with a printf-style C ABI. Every record is written to stderr (the C++ stderr_sink parity) and additionally forwarded to the log crate's global logger when the host has installed one. oakcommon never installs a global logger itself — the C ABI is loaded into hosts that set their own, and log::set_logger can only be called once per process.
  6. OCIO / OIIO / FFmpeg: ocioutils.rs talks to real OpenColorIO through the crates.io ocio-rs bindings (OcioConfig/OcioProcessor, BitDepth enum — no hand-written constant tables); oiioutils.rs derives its OIIO base-type mapping from the image crate's color-type tables (HALF pinned from the frozen OIIO table — image has no f16 sample type) and converts aspect ratios with oakcore_rs::Rational::from_double — a hand-written port of FFmpeg's av_d2q matching the C++ Rational::from_double exactly, kept in the leaf crate rather than adding ffmpeg-next/ffmpeg-sys-next (narrow extern C discipline). 32-bit float image I/O (F32Image) is pure image. All adopted crates are registered in the table above.

Layout

src/
  lib.rs            crate doc + module map
  error.rs          error codes (include/common/error.h)
  handle.rs         refcounted-handle scaffolding
  configstore.rs    INI config (include/common/config.h)
  commandlineparser.rs
  xmlutils.rs       streaming XML reader/writer
  filefunctions.rs  file/dir helpers
  debug.rs          leveled logging
  ffmpegutils.rs    pixfmt/samplefmt mapping (via ffmpeg_bridge C ABI)
  ocioutils.rs      OCIO queries
  oiioutils.rs      OIIO queries
  videoparams.rs    VideoParams plain data + queries
  subtitleparams.rs SubtitleParams
  colortransform.rs ColorTransform plain data
  miscutils.rs      misc (loop mode, drop behavior, power, current…)
  ffi.rs            export layer (one submodule per public header)
tests/              contract tests per module

Testing

cargo test --release --features test-stubs runs the full suite: unit tests, C ABI contract tests, and the integration tests (incl. tests/ffi_ffmpegutils.rs). The test-stubs feature substitutes the in-crate ffmpeg_bridge mock (fb_find_best_pix_fmt_of_list stub, see src/ffmpegutils.rs) so the C ABI tests link without libffmpeg_bridge; without the feature that symbol is imported from ffmpeg_bridge at link time. This mirrors the test-stubs convention of oakplugin / oaktimeline.