refactor: drop internal bridge/ffi layers; exporter family lands

Single-lib cleanup: the per-crate src/bridge/ and src/ffi.rs layers are
gone (oakundo/oakcommon/oaknode/oaktimeline/oakcodec/oakaudio/
oakrender/oaktask/oakplugin/oakstorage); cross-crate calls are plain
Rust, CHandle marshalling shrinks to the oakengine boundary, and tests
call the Rust APIs directly (pure C-ABI wrapper tests removed where
the domain layer already covers the behavior).

exporter.h family implemented: oakengine_export_render (CLI contract),
oakengine_export_render_with_params (was a stub), last_error and
progress callback; synchronous path reuses task_create_export +
start_sync. Fixes on the way: oaktask video ticket self-deadlock,
audio params dropped on the export path, codec encoder AAC slicing and
H.264 time base. Real-mp4 tests cover both entry points, progress and
the illegal-argument matrix.

Also: oakstorage session maps null project handles to None (version-
info path), configstore test double literal 3.14 -> 3.15 (clippy PI
lint), oakaudio output callback scratch buffer + env-aware P1 test,
cli media round-trip test uses a generated 16-frame clip (no more
minute-long debug runs).
This commit is contained in:
2026-08-16 00:33:45 +08:00
parent 2248be8567
commit ab1a2e9c7b
293 changed files with 27826 additions and 90128 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
//!
//! Note: OpenColorIO itself is never linked here; it is reached through
//! the color manager (`crate::colormanager`) and the oakrender bridge
//! (`crate::bridge::render`), like the C++ node's
//! (oakrender, opaque handles), like the C++ node's
//! `oaknode_colormanager_*` / `oakrender_color_processor_*` calls.
use crate::factory::NodeMeta;
@@ -93,7 +93,7 @@ impl GeneratorWithMerge {
/// and the un-merged case pushes `job` itself.
pub fn push_mergable_job(
inputs: &crate::value::NodeValueRow,
job: crate::bridge::render::TextureHandle,
job: crate::handle::CHandle,
table: &mut crate::value::NodeValueTable,
) {
match inputs.get(BASE_INPUT) {
+1 -1
View File
@@ -22,7 +22,7 @@
//! undo commands `NodeGroupAddInputPassthrough` /
//! `NodeGroupSetOutputPassthrough`; the C ABI's undoable variants
//! (`include/node/group.h`) build equivalent vtable commands through
//! `bridge::undo` in the ffi layer.
//! oakundo commands in the ops layer.
use crate::factory::NodeMeta;
use crate::graph::Graph;
+5 -5
View File
@@ -25,7 +25,7 @@
//!
//! Note: OpenColorIO itself is never linked here. All OCIO work goes
//! through the color manager (`crate::colormanager`) and the oakrender
//! bridge (`crate::bridge::render`), mirroring how the C++ node calls
//! bridge (opaque oakrender handles), mirroring how the C++ node calls
//! `oakrender_color_processor_*` / `oaknode_colormanager_*` C functions
//! instead of using OCIO directly.
@@ -47,13 +47,13 @@ pub const TEXTURE_INPUT: &str = "tex_in";
/// bridge), so the field is omitted here: `added_to_graph` /
/// `removed_from_graph` document the capture/clear, and the processor
/// generation helpers reach the manager through
/// `crate::colormanager`/`crate::bridge::render` at call time.
/// `crate::colormanager`/oakrender at call time.
pub struct OcioBase {
/// Owned color processor handle (C++ `processor_`, an
/// `OakColorProcessor`); `None`/empty while no valid processor has
/// been generated. Released with the node (C++ destructor calls
/// `oakrender_color_processor_free`).
processor: Option<crate::bridge::render::ColorProcessorHandle>,
processor: Option<crate::handle::CHandle>,
}
// The processor handle wraps a refcounted C object that is only
@@ -74,7 +74,7 @@ impl OcioBase {
/// Borrowed view of the owned processor handle (C++
/// `OCIOBaseNode::processor()`; callers must NOT free it).
pub fn processor(&self) -> Option<&crate::bridge::render::ColorProcessorHandle> {
pub fn processor(&self) -> Option<&crate::handle::CHandle> {
self.processor.as_ref()
}
@@ -83,7 +83,7 @@ impl OcioBase {
/// `OakColorProcessor` before storing the new one).
pub fn set_processor(
&mut self,
processor: Option<crate::bridge::render::ColorProcessorHandle>,
processor: Option<crate::handle::CHandle>,
) {
// The C++ frees the previous processor via
// `oakrender_color_processor_free`; the Rust handle is a
@@ -20,7 +20,7 @@
//!
//! Note: OpenColorIO itself is never linked here; it is reached through
//! the color manager (`crate::colormanager`) and the oakrender bridge
//! (`crate::bridge::render`), like the C++ node's
//! (oakrender, opaque handles), like the C++ node's
//! `oakrender_color_processor_create_grading_primary` call.
use crate::factory::NodeMeta;
@@ -25,7 +25,7 @@
//!
//! Note: OpenColorIO itself is never linked here; it is reached through
//! the color manager (`crate::colormanager`) and the oakrender bridge
//! (`crate::bridge::render`), like the C++ node's
//! (oakrender, opaque handles), like the C++ node's
//! `oakrender_color_processor_create_grading_primary` call.
use crate::factory::NodeMeta;
+2 -2
View File
@@ -19,7 +19,7 @@
//!
//! Note: OpenColorIO itself is never linked here; it is reached through
//! the color manager (`crate::colormanager`) and the oakrender bridge
//! (`crate::bridge::render`), like the C++ node's
//! (oakrender, opaque handles), like the C++ node's
//! `oakrender_color_processor_create_lut` / `oakrender_lut_*` calls.
use std::sync::Mutex;
@@ -57,7 +57,7 @@ struct ProcessorState {
last_direction: i64,
/// Cached processor for change detection (C++ `last_processor_`);
/// released with the node.
last_processor: Option<crate::bridge::render::ColorProcessorHandle>,
last_processor: Option<crate::handle::CHandle>,
/// Human-readable reason no LUT processor is active (C++
/// `last_error_`); empty when a valid processor is in use or no LUT
/// file has been selected yet.
+3 -3
View File
@@ -19,7 +19,7 @@
//!
//! DECLARATION ONLY. This node is a thin wrapper over an OFX plugin
//! instance that lives behind the `oakplugin` crate's C ABI bridge
//! (`crate::bridge`); no OFX types (`OFX::Host::ImageEffect::Instance`,
//! (opaque oakrender handles); no OFX types (`OFX::Host::ImageEffect::Instance`,
//! `kOfxParam*`, ...) are declared here. The plugin instance is
//! represented as the opaque [`PluginInstanceHandle`] below — the real
//! definition belongs to the oakplugin bridge module and this draft
@@ -242,14 +242,14 @@ impl NodeBehavior for PluginNode {
/// the destination frame if needed and zero-fills it (plugins do
/// their real image work in the plugin job, not here).
///
/// The Rust frame is an opaque [`crate::bridge::render::TextureHandle`]
/// The Rust frame is an opaque [`crate::handle::CHandle`]
/// whose pixels cannot be read or written from this crate, so the
/// body is a documented no-op (`// CPP-PARITY: plugin.cpp`
/// `generate_frame`).
fn generate_frame(
&self,
core: &NodeCore,
frame: &mut crate::bridge::render::TextureHandle,
frame: &mut crate::handle::CHandle,
time: Rational,
) {
let _ = (core, frame, time);
+2 -2
View File
@@ -136,7 +136,7 @@ impl NodeBehavior for PolygonGenerator {
/// scaling and center translation; without a backend the frame is
/// left empty (warned once).
///
/// The Rust `frame` is an opaque [`crate::bridge::render::TextureHandle`]
/// The Rust `frame` is an opaque [`crate::handle::CHandle`]
/// whose bytes cannot be touched, and this crate has no path-fill
/// backend — so neither the clear nor the fill is representable here
/// (`// CPP-PARITY: polygon.cpp` `generate_frame`). The path building
@@ -145,7 +145,7 @@ impl NodeBehavior for PolygonGenerator {
fn generate_frame(
&self,
core: &NodeCore,
frame: &mut crate::bridge::render::TextureHandle,
frame: &mut crate::handle::CHandle,
time: oakcore_rs::Rational,
) {
let _ = (core, frame, time);
+2 -2
View File
@@ -241,7 +241,7 @@ impl NodeBehavior for TextGeneratorV1 {
/// into the float frame multiplied by the color input. With no
/// backend installed, warns once and leaves the frame empty.
///
/// The Rust frame is an opaque [`crate::bridge::render::TextureHandle`]
/// The Rust frame is an opaque [`crate::handle::CHandle`]
/// whose pixels cannot be read or written from this crate, so the
/// body is a documented no-op; the layout/measure/offset control flow
/// is ported in [`Self::layout_request`], [`Self::draw_offsets`] and
@@ -249,7 +249,7 @@ impl NodeBehavior for TextGeneratorV1 {
fn generate_frame(
&self,
core: &NodeCore,
frame: &mut crate::bridge::render::TextureHandle,
frame: &mut crate::handle::CHandle,
time: Rational,
) {
let _ = (core, frame, time);
+2 -2
View File
@@ -301,7 +301,7 @@ impl NodeBehavior for TextGeneratorV2 {
/// identical). With no backend installed, warns once and leaves
/// the frame empty.
///
/// The Rust frame is an opaque [`crate::bridge::render::TextureHandle`]
/// The Rust frame is an opaque [`crate::handle::CHandle`]
/// whose pixels cannot be read or written from this crate, so the
/// body is a documented no-op; the layout/measure/offset control flow
/// is ported in [`Self::layout_request`], [`Self::base_offset`],
@@ -310,7 +310,7 @@ impl NodeBehavior for TextGeneratorV2 {
fn generate_frame(
&self,
core: &NodeCore,
frame: &mut crate::bridge::render::TextureHandle,
frame: &mut crate::handle::CHandle,
time: Rational,
) {
let _ = (core, frame, time);
+2 -2
View File
@@ -342,7 +342,7 @@ impl NodeBehavior for TextGeneratorV3 {
/// backend installed, warns once and leaves the cleared frame
/// untouched.
///
/// The Rust frame is an opaque [`crate::bridge::render::TextureHandle`]
/// The Rust frame is an opaque [`crate::handle::CHandle`]
/// whose pixels cannot be read or written from this crate, so the
/// body is a documented no-op; the layout/measure/offset control flow
/// is ported in [`Self::layout_request`], [`Self::base_offset`] and
@@ -350,7 +350,7 @@ impl NodeBehavior for TextGeneratorV3 {
fn generate_frame(
&self,
core: &NodeCore,
frame: &mut crate::bridge::render::TextureHandle,
frame: &mut crate::handle::CHandle,
time: Rational,
) {
let _ = (core, frame, time);